FAILURE MAP
← Case archive

FA-65991 / Aviation weight and balance / Open access

Ballast lever measured to the current CG · case 01

The computed ballast leaves the CG slightly outside the limit.

Verified by executionVariant 1 · 13 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The denominator uses distance from ballast arm to the current CG instead of to the target limit.

THE FAILURE

The denominator uses distance from ballast arm to the current CG instead of to the target limit.

Unsuccessful approach: Always using the aft limit in the denominator is right for aft violations but wrong for forward ones.

Case contract

Input [W lb, CG, fwd limit, aft limit, ballast arm, max weight]. Inside inclusive limits -> 0. Otherwise ballast B brings CG to the violated limit: B = W*(CG-limit)/(limit-arm), rounded up to whole lb; ballast arm not on the corrective side of that limit -> 'ERR_BALLAST_ARM'; W+B above max -> 'ERR_OVERWEIGHT'.

Why this case matters

Ballast adds weight at a fixed station; the required amount depends on the distance from the ballast arm to the violated limit, and adds to gross weight.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    W, cg, fwd, aft, ba, maxw = x
    if fwd <= cg <= aft: return 0
    lim = aft if cg > aft else fwd
    if (cg > aft and ba >= aft) or (cg < fwd and ba <= fwd): return 'ERR_BALLAST_ARM'
    b = math.ceil(round(W * (cg - lim) / (cg - ba), 6))
    if W + b > maxw: return 'ERR_OVERWEIGHT'
    return b
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['aft CG nose ballast', [1800, 48.0, 35.0, 47.3, 10.0, 2550], 34], ['forward CG tail ballast', [1700, 34.2, 35.05, 47.3, 150.0, 2550], 13], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 21.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2250, 36.0, 36.0, 46.0, 101.0, 2700], 0], ['sampled case 2', [2220, 44.7, 33.9, 44.7, 121.5, 2550], 0], ['sampled case 3', [2400, 39.05, 36.3, 46.8, 9.5, 2400], 0], ['regression: ballast lever distance', [1765, 32.01, 34.1, 46.8, 54.4, 2550], 182]], [['aft CG nose ballast', [1800, 48.1, 35.0, 47.3, 10.0, 2550], 39], ['forward CG tail ballast', [1700, 34.2, 35.1, 47.3, 150.0, 2550], 14], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 22.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2035, 44.73, 36.5, 45.1, 11.9, 3000], 0], ['sampled case 2', [1925, 46.69, 36.9, 45.7, 120.5, 2550], 'ERR_BALLAST_ARM'], ['sampled case 3', [2440, 47.5, 35.1, 47.5, 46.2, 2400], 0]], [['aft CG nose ballast', [1800, 48.199999999999996, 35.0, 47.3, 10.0, 2550], 44], ['forward CG tail ballast', [1700, 34.2, 35.15, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 23.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2510, 41.12, 36.1, 47.4, 155.2, 2700], 0], ['sampled case 2', [1785, 32.94, 35.6, 44.4, 94.3, 2400], 81], ['sampled case 3', [2400, 37.65, 34.3, 45.9, 140.6, 2550], 0]], [['aft CG nose ballast', [1800, 48.3, 35.0, 47.3, 10.0, 2550], 49], ['forward CG tail ballast', [1700, 34.2, 35.2, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 24.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1590, 30.16, 33.1, 46.2, 118.7, 2550], 55], ['sampled case 2', [1710, 32.9, 34.8, 45.0, 129.9, 2550], 35], ['sampled case 3', [1755, 35.34, 36.3, 47.0, 127.7, 2700], 19]], [['aft CG nose ballast', [1800, 48.4, 35.0, 47.3, 10.0, 2550], 54], ['forward CG tail ballast', [1700, 34.2, 35.25, 47.3, 150.0, 2550], 16], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 25.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1745, 31.68, 34.3, 46.9, 112.4, 2550], 59], ['sampled case 2', [1645, 34.52, 36.5, 47.5, 5.2, 2400], 'ERR_BALLAST_ARM'], ['sampled case 3', [1850, 32.93, 34.5, 46.9, 56.9, 2700], 130]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
aft CG nose ballast3434Passed
forward CG tail ballast1313Passed
in envelope00Passed
exactly on aft limit00Passed
exactly on forward limit00Passed
ballast arm behind aft limitERR_BALLAST_ARMERR_BALLAST_ARMPassed
forward case ballast in noseERR_BALLAST_ARMERR_BALLAST_ARMPassed
ballast would overweightERR_OVERWEIGHTERR_OVERWEIGHTPassed
ballast reaches exactly max1010Passed
sampled case 100Passed
sampled case 200Passed
sampled case 300Passed
regression: ballast lever distance165182Failed

SHA-256 / 40853ba382efd627fe4fc19ee3fd60385bca837d7fdbda3d0f93c7dd21af65fd

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    W, cg, fwd, aft, ba, maxw = x
    if fwd <= cg <= aft: return 0
    lim = aft if cg > aft else fwd
    if (cg > aft and ba >= aft) or (cg < fwd and ba <= fwd): return 'ERR_BALLAST_ARM'
    b = math.ceil(round(W * (cg - lim) / (aft - ba), 6))
    if W + b > maxw: return 'ERR_OVERWEIGHT'
    return b
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['aft CG nose ballast', [1800, 48.0, 35.0, 47.3, 10.0, 2550], 34], ['forward CG tail ballast', [1700, 34.2, 35.05, 47.3, 150.0, 2550], 13], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 21.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2250, 36.0, 36.0, 46.0, 101.0, 2700], 0], ['sampled case 2', [2220, 44.7, 33.9, 44.7, 121.5, 2550], 0], ['sampled case 3', [2400, 39.05, 36.3, 46.8, 9.5, 2400], 0], ['regression: ballast lever distance', [1765, 32.01, 34.1, 46.8, 54.4, 2550], 182]], [['aft CG nose ballast', [1800, 48.1, 35.0, 47.3, 10.0, 2550], 39], ['forward CG tail ballast', [1700, 34.2, 35.1, 47.3, 150.0, 2550], 14], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 22.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2035, 44.73, 36.5, 45.1, 11.9, 3000], 0], ['sampled case 2', [1925, 46.69, 36.9, 45.7, 120.5, 2550], 'ERR_BALLAST_ARM'], ['sampled case 3', [2440, 47.5, 35.1, 47.5, 46.2, 2400], 0]], [['aft CG nose ballast', [1800, 48.199999999999996, 35.0, 47.3, 10.0, 2550], 44], ['forward CG tail ballast', [1700, 34.2, 35.15, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 23.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2510, 41.12, 36.1, 47.4, 155.2, 2700], 0], ['sampled case 2', [1785, 32.94, 35.6, 44.4, 94.3, 2400], 81], ['sampled case 3', [2400, 37.65, 34.3, 45.9, 140.6, 2550], 0]], [['aft CG nose ballast', [1800, 48.3, 35.0, 47.3, 10.0, 2550], 49], ['forward CG tail ballast', [1700, 34.2, 35.2, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 24.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1590, 30.16, 33.1, 46.2, 118.7, 2550], 55], ['sampled case 2', [1710, 32.9, 34.8, 45.0, 129.9, 2550], 35], ['sampled case 3', [1755, 35.34, 36.3, 47.0, 127.7, 2700], 19]], [['aft CG nose ballast', [1800, 48.4, 35.0, 47.3, 10.0, 2550], 54], ['forward CG tail ballast', [1700, 34.2, 35.25, 47.3, 150.0, 2550], 16], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 25.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1745, 31.68, 34.3, 46.9, 112.4, 2550], 59], ['sampled case 2', [1645, 34.52, 36.5, 47.5, 5.2, 2400], 'ERR_BALLAST_ARM'], ['sampled case 3', [1850, 32.93, 34.5, 46.9, 56.9, 2700], 130]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
aft CG nose ballast3434Passed
forward CG tail ballast1513Failed
in envelope00Passed
exactly on aft limit00Passed
exactly on forward limit00Passed
ballast arm behind aft limitERR_BALLAST_ARMERR_BALLAST_ARMPassed
forward case ballast in noseERR_BALLAST_ARMERR_BALLAST_ARMPassed
ballast would overweightERR_OVERWEIGHTERR_OVERWEIGHTPassed
ballast reaches exactly max1010Passed
sampled case 100Passed
sampled case 200Passed
sampled case 300Passed
regression: ballast lever distance486182Failed

SHA-256 / ef38e08183157944ec0edfe5ac31775fff77cddf686112107ac8ce33d20c5541

HELD IN THE MEMBER ARCHIVE

The verified repair and its recorded checks are member-only.

This mechanism has 13 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.

Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.

Member access is invitation-based. Sign in with your invited account to inspect the repair.

Sign in to the archive ↗

Verification & scope

A deterministic toy loading model with stipulated constants; it is not an approved aircraft flight manual procedure and makes no claim of regulatory conformance. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:47:39.125425+00:00.

Case digest / f956d2a5d9d6a1b80d4aad9911787b89b2c7ecf47ab4b76cb1b9e38ac490f176