FAILURE MAP
← Case archive

FA-8006 / Form validation / Open access

Validation message disclosure: Disabled fields expose stale validation errors · case 01

Disabled fields expose stale validation errors.

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

ROOT CAUSE

The disabled operation uses `if disabled: return error` where the contract requires `if disabled: return 'hidden'`.

VERIFIED REPAIR

Implement the disabled operation as `if disabled: return 'hidden'`.

Unsuccessful approach: Hiding enabled fields suppresses actionable messages.

Case contract

Disabled fields hide errors; pending takes precedence; None alone means valid; errors become visible on touch or submit.

Why this case matters

A deterministic model of validation message disclosure; this isolates one interface invariant without requiring a browser.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(error, touched, submitted, disabled, pending):
    if disabled: return error
    if pending: return 'checking'
    if error is None: return 'valid'
    if touched or submitted: return error
    return 'hidden'
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('disabled', solve('required', True, True, True, False), 'hidden')
check('pending', solve('stale', True, True, False, True), 'checking')
check('empty error', solve('', True, False, False, False), '')
check('submit', solve('required', False, True, False, False), 'required')
check('touched', solve('required', True, False, False, False), 'required')
check('pristine', solve('required', False, False, False, False), 'hidden')
check('valid', solve(None, True, True, False, False), 'valid')
check('parameterized error', solve('error'+str(N), False, True, False, False), 'error'+str(N))
for repetition in range(N):
    check('repeat valid', solve(None, True, True, False, False), 'valid')
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
disabledrequiredhiddenFailed
pendingcheckingcheckingPassed
empty errorPassed
submitrequiredrequiredPassed
touchedrequiredrequiredPassed
pristinehiddenhiddenPassed
validvalidvalidPassed
parameterized errorerror1error1Passed
repeat validvalidvalidPassed

SHA-256 / 2d4a858dc711c06342bbcff85ca564f403e235ad92842a1bd9088a8cfe430a79

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(error, touched, submitted, disabled, pending):
    if not disabled: return 'hidden'
    if pending: return 'checking'
    if error is None: return 'valid'
    if touched or submitted: return error
    return 'hidden'
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('disabled', solve('required', True, True, True, False), 'hidden')
check('pending', solve('stale', True, True, False, True), 'checking')
check('empty error', solve('', True, False, False, False), '')
check('submit', solve('required', False, True, False, False), 'required')
check('touched', solve('required', True, False, False, False), 'required')
check('pristine', solve('required', False, False, False, False), 'hidden')
check('valid', solve(None, True, True, False, False), 'valid')
check('parameterized error', solve('error'+str(N), False, True, False, False), 'error'+str(N))
for repetition in range(N):
    check('repeat valid', solve(None, True, True, False, False), 'valid')
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
disabledrequiredhiddenFailed
pendinghiddencheckingFailed
empty errorhiddenFailed
submithiddenrequiredFailed
touchedhiddenrequiredFailed
pristinehiddenhiddenPassed
validhiddenvalidFailed
parameterized errorhiddenerror1Failed
repeat validhiddenvalidFailed

SHA-256 / 0931a8034f08c3f80de489a44c2f4107fe7088f523134d9759165bc2dfdb3491

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(error, touched, submitted, disabled, pending):
    if disabled: return 'hidden'
    if pending: return 'checking'
    if error is None: return 'valid'
    if touched or submitted: return error
    return 'hidden'
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('disabled', solve('required', True, True, True, False), 'hidden')
check('pending', solve('stale', True, True, False, True), 'checking')
check('empty error', solve('', True, False, False, False), '')
check('submit', solve('required', False, True, False, False), 'required')
check('touched', solve('required', True, False, False, False), 'required')
check('pristine', solve('required', False, False, False, False), 'hidden')
check('valid', solve(None, True, True, False, False), 'valid')
check('parameterized error', solve('error'+str(N), False, True, False, False), 'error'+str(N))
for repetition in range(N):
    check('repeat valid', solve(None, True, True, False, False), 'valid')
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
disabledhiddenhiddenPassed
pendingcheckingcheckingPassed
empty errorPassed
submitrequiredrequiredPassed
touchedrequiredrequiredPassed
pristinehiddenhiddenPassed
validvalidvalidPassed
parameterized errorerror1error1Passed
repeat validvalidvalidPassed

SHA-256 / 6b97df8e4e85b74b3334a8680e9d6f6b2061ecd538af350f035faf38f60982e6

Verification & scope

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:38:17.402456+00:00.

Case digest / 8f87c956f7f4dc9467443d066187dbb8d5d84ed05d7da091a5777c9af2dddfe7