FAILURE MAP
← Case archive

FA-28876 / HTTP redirects / Open access

Serialize a redirect response under an explicit server-side response policy: custom response fields retained · case 01

Serialize a redirect response under an explicit server-side response policy: the custom response fields retained branch emits an incorrect decision.

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

ROOT CAUSE

The custom-response-fields-retained decision uses '{}'; this violates the stipulated controller policy.

VERIFIED REPAIR

At this decision use 'custom_headers', preserving the other controller outputs.

Unsuccessful approach: The partial repair uses "{k:v for k,v in custom_headers.items() if k.startswith('Content-')}" and still fails an explicit boundary or control.

Case contract

Serialize a redirect response under an explicit server-side response policy. The explicit fixture inputs and outputs define a bounded offline policy; request identity must accompany the decision.

Why this case matters

Models a redirect controller decision before following a target or exposing a redirect result.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
from urllib.parse import urlsplit, unquote, quote
import posixpath
import re
N = 1
observations = []
def solve(request, status, target, method, body, head, custom_headers):
    return {'request': request, 'decision': [dict(custom_headers, Location=target), '' if head else body, len(body.encode('utf-8')), status, target.replace('&','&'), target.replace(chr(34),'"'), target, {}, body == "", status == 303]} 
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('fixture 1', solve('/requests/' + str(N) + '/0', 302, '/a?x=1&y=2', 'GET', 'move', False, {'X': 'v'}), {'request': '/requests/' + str(N) + '/0', 'decision': [{'X': 'v', 'Location': '/a?x=1&y=2'}, 'move', 4, 302, '/a?x=1&y=2', '/a?x=1&y=2', '/a?x=1&y=2', {'X': 'v'}, False, False]})
check('fixture 2', solve('/requests/' + str(N) + '/1', 303, '/a#part', 'POST', 'next', False, {}), {'request': '/requests/' + str(N) + '/1', 'decision': [{'Location': '/a#part'}, 'next', 4, 303, '/a#part', '/a#part', '/a#part', {}, False, True]})
check('fixture 3', solve('/requests/' + str(N) + '/2', 307, '/unicode/é', 'PUT', 'café', True, {'Content-Length': '999'}), {'request': '/requests/' + str(N) + '/2', 'decision': [{'Content-Length': '999', 'Location': '/unicode/é'}, '', 5, 307, '/unicode/é', '/unicode/é', '/unicode/é', {'Content-Length': '999'}, False, False]})
check('fixture 4', solve('/requests/' + str(N) + '/3', 308, '/', 'HEAD', 'moved', True, {}), {'request': '/requests/' + str(N) + '/3', 'decision': [{'Location': '/'}, '', 5, 308, '/', '/', '/', {}, False, False]})
check('fixture 5', solve('/requests/' + str(N) + '/4', 301, '/b', 'GET', '', False, {'Location': '/stale'}), {'request': '/requests/' + str(N) + '/4', 'decision': [{'Location': '/b'}, '', 0, 301, '/b', '/b', '/b', {'Location': '/stale'}, True, False]})
check('fixture 6', solve('/requests/' + str(N) + '/5', 302, '/a"b', 'GET', 'x', False, {'Content-Type': 'custom'}), {'request': '/requests/' + str(N) + '/5', 'decision': [{'Content-Type': 'custom', 'Location': '/a"b'}, 'x', 1, 302, '/a"b', '/a"b', '/a"b', {'Content-Type': 'custom'}, False, False]})
check('fixture 7', solve('/requests/' + str(N) + '/6', 303, '/e', 'GET', 'abc', False, {}), {'request': '/requests/' + str(N) + '/6', 'decision': [{'Location': '/e'}, 'abc', 3, 303, '/e', '/e', '/e', {}, False, True]})
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
fixture 1{'decision': [{'Location': '/a?x=1&y=2', 'X': 'v'}, 'move', 4, 302, '/a?x=1&y=2', '/a?x=1&y=2', '/a?x=1&y=2', {}, False, False], 'request': '/requests/1/0'}{'decision': [{'Location': '/a?x=1&y=2', 'X': 'v'}, 'move', 4, 302, '/a?x=1&y=2', '/a?x=1&y=2', '/a?x=1&y=2', {'X': 'v'}, False, False], 'request': '/requests/1/0'}Failed
fixture 2{'decision': [{'Location': '/a#part'}, 'next', 4, 303, '/a#part', '/a#part', '/a#part', {}, False, True], 'request': '/requests/1/1'}{'decision': [{'Location': '/a#part'}, 'next', 4, 303, '/a#part', '/a#part', '/a#part', {}, False, True], 'request': '/requests/1/1'}Passed
fixture 3{'decision': [{'Content-Length': '999', 'Location': '/unicode/é'}, '', 5, 307, '/unicode/é', '/unicode/é', '/unicode/é', {}, False, False], 'request': '/requests/1/2'}{'decision': [{'Content-Length': '999', 'Location': '/unicode/é'}, '', 5, 307, '/unicode/é', '/unicode/é', '/unicode/é', {'Content-Length': '999'}, False, False], 'request': '/requests/1/2'}Failed
fixture 4{'decision': [{'Location': '/'}, '', 5, 308, '/', '/', '/', {}, False, False], 'request': '/requests/1/3'}{'decision': [{'Location': '/'}, '', 5, 308, '/', '/', '/', {}, False, False], 'request': '/requests/1/3'}Passed
fixture 5{'decision': [{'Location': '/b'}, '', 0, 301, '/b', '/b', '/b', {}, True, False], 'request': '/requests/1/4'}{'decision': [{'Location': '/b'}, '', 0, 301, '/b', '/b', '/b', {'Location': '/stale'}, True, False], 'request': '/requests/1/4'}Failed
fixture 6{'decision': [{'Content-Type': 'custom', 'Location': '/a"b'}, 'x', 1, 302, '/a"b', '/a"b', '/a"b', {}, False, False], 'request': '/requests/1/5'}{'decision': [{'Content-Type': 'custom', 'Location': '/a"b'}, 'x', 1, 302, '/a"b', '/a"b', '/a"b', {'Content-Type': 'custom'}, False, False], 'request': '/requests/1/5'}Failed
fixture 7{'decision': [{'Location': '/e'}, 'abc', 3, 303, '/e', '/e', '/e', {}, False, True], 'request': '/requests/1/6'}{'decision': [{'Location': '/e'}, 'abc', 3, 303, '/e', '/e', '/e', {}, False, True], 'request': '/requests/1/6'}Passed

SHA-256 / beef7ad1eb8953e3b5984d2080917376073bf1e3cd9d98f35e8bc30d3e8c8b55

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
from urllib.parse import urlsplit, unquote, quote
import posixpath
import re
N = 1
observations = []
def solve(request, status, target, method, body, head, custom_headers):
    return {'request': request, 'decision': [dict(custom_headers, Location=target), '' if head else body, len(body.encode('utf-8')), status, target.replace('&','&'), target.replace(chr(34),'"'), target, {k:v for k,v in custom_headers.items() if k.startswith('Content-')}, body == "", status == 303]} 
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('fixture 1', solve('/requests/' + str(N) + '/0', 302, '/a?x=1&y=2', 'GET', 'move', False, {'X': 'v'}), {'request': '/requests/' + str(N) + '/0', 'decision': [{'X': 'v', 'Location': '/a?x=1&y=2'}, 'move', 4, 302, '/a?x=1&y=2', '/a?x=1&y=2', '/a?x=1&y=2', {'X': 'v'}, False, False]})
check('fixture 2', solve('/requests/' + str(N) + '/1', 303, '/a#part', 'POST', 'next', False, {}), {'request': '/requests/' + str(N) + '/1', 'decision': [{'Location': '/a#part'}, 'next', 4, 303, '/a#part', '/a#part', '/a#part', {}, False, True]})
check('fixture 3', solve('/requests/' + str(N) + '/2', 307, '/unicode/é', 'PUT', 'café', True, {'Content-Length': '999'}), {'request': '/requests/' + str(N) + '/2', 'decision': [{'Content-Length': '999', 'Location': '/unicode/é'}, '', 5, 307, '/unicode/é', '/unicode/é', '/unicode/é', {'Content-Length': '999'}, False, False]})
check('fixture 4', solve('/requests/' + str(N) + '/3', 308, '/', 'HEAD', 'moved', True, {}), {'request': '/requests/' + str(N) + '/3', 'decision': [{'Location': '/'}, '', 5, 308, '/', '/', '/', {}, False, False]})
check('fixture 5', solve('/requests/' + str(N) + '/4', 301, '/b', 'GET', '', False, {'Location': '/stale'}), {'request': '/requests/' + str(N) + '/4', 'decision': [{'Location': '/b'}, '', 0, 301, '/b', '/b', '/b', {'Location': '/stale'}, True, False]})
check('fixture 6', solve('/requests/' + str(N) + '/5', 302, '/a"b', 'GET', 'x', False, {'Content-Type': 'custom'}), {'request': '/requests/' + str(N) + '/5', 'decision': [{'Content-Type': 'custom', 'Location': '/a"b'}, 'x', 1, 302, '/a"b', '/a"b', '/a"b', {'Content-Type': 'custom'}, False, False]})
check('fixture 7', solve('/requests/' + str(N) + '/6', 303, '/e', 'GET', 'abc', False, {}), {'request': '/requests/' + str(N) + '/6', 'decision': [{'Location': '/e'}, 'abc', 3, 303, '/e', '/e', '/e', {}, False, True]})
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
fixture 1{'decision': [{'Location': '/a?x=1&y=2', 'X': 'v'}, 'move', 4, 302, '/a?x=1&y=2', '/a?x=1&y=2', '/a?x=1&y=2', {}, False, False], 'request': '/requests/1/0'}{'decision': [{'Location': '/a?x=1&y=2', 'X': 'v'}, 'move', 4, 302, '/a?x=1&y=2', '/a?x=1&y=2', '/a?x=1&y=2', {'X': 'v'}, False, False], 'request': '/requests/1/0'}Failed
fixture 2{'decision': [{'Location': '/a#part'}, 'next', 4, 303, '/a#part', '/a#part', '/a#part', {}, False, True], 'request': '/requests/1/1'}{'decision': [{'Location': '/a#part'}, 'next', 4, 303, '/a#part', '/a#part', '/a#part', {}, False, True], 'request': '/requests/1/1'}Passed
fixture 3{'decision': [{'Content-Length': '999', 'Location': '/unicode/é'}, '', 5, 307, '/unicode/é', '/unicode/é', '/unicode/é', {'Content-Length': '999'}, False, False], 'request': '/requests/1/2'}{'decision': [{'Content-Length': '999', 'Location': '/unicode/é'}, '', 5, 307, '/unicode/é', '/unicode/é', '/unicode/é', {'Content-Length': '999'}, False, False], 'request': '/requests/1/2'}Passed
fixture 4{'decision': [{'Location': '/'}, '', 5, 308, '/', '/', '/', {}, False, False], 'request': '/requests/1/3'}{'decision': [{'Location': '/'}, '', 5, 308, '/', '/', '/', {}, False, False], 'request': '/requests/1/3'}Passed
fixture 5{'decision': [{'Location': '/b'}, '', 0, 301, '/b', '/b', '/b', {}, True, False], 'request': '/requests/1/4'}{'decision': [{'Location': '/b'}, '', 0, 301, '/b', '/b', '/b', {'Location': '/stale'}, True, False], 'request': '/requests/1/4'}Failed
fixture 6{'decision': [{'Content-Type': 'custom', 'Location': '/a"b'}, 'x', 1, 302, '/a"b', '/a"b', '/a"b', {'Content-Type': 'custom'}, False, False], 'request': '/requests/1/5'}{'decision': [{'Content-Type': 'custom', 'Location': '/a"b'}, 'x', 1, 302, '/a"b', '/a"b', '/a"b', {'Content-Type': 'custom'}, False, False], 'request': '/requests/1/5'}Passed
fixture 7{'decision': [{'Location': '/e'}, 'abc', 3, 303, '/e', '/e', '/e', {}, False, True], 'request': '/requests/1/6'}{'decision': [{'Location': '/e'}, 'abc', 3, 303, '/e', '/e', '/e', {}, False, True], 'request': '/requests/1/6'}Passed

SHA-256 / 7f27f63a0392d68fccbfb11d3abe8d40a5cbaced9dc1d3886d3b34c78910c62f

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
from urllib.parse import urlsplit, unquote, quote
import posixpath
import re
N = 1
observations = []
def solve(request, status, target, method, body, head, custom_headers):
    return {'request': request, 'decision': [dict(custom_headers, Location=target), '' if head else body, len(body.encode('utf-8')), status, target.replace('&','&'), target.replace(chr(34),'"'), target, custom_headers, body == "", status == 303]} 
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('fixture 1', solve('/requests/' + str(N) + '/0', 302, '/a?x=1&y=2', 'GET', 'move', False, {'X': 'v'}), {'request': '/requests/' + str(N) + '/0', 'decision': [{'X': 'v', 'Location': '/a?x=1&y=2'}, 'move', 4, 302, '/a?x=1&y=2', '/a?x=1&y=2', '/a?x=1&y=2', {'X': 'v'}, False, False]})
check('fixture 2', solve('/requests/' + str(N) + '/1', 303, '/a#part', 'POST', 'next', False, {}), {'request': '/requests/' + str(N) + '/1', 'decision': [{'Location': '/a#part'}, 'next', 4, 303, '/a#part', '/a#part', '/a#part', {}, False, True]})
check('fixture 3', solve('/requests/' + str(N) + '/2', 307, '/unicode/é', 'PUT', 'café', True, {'Content-Length': '999'}), {'request': '/requests/' + str(N) + '/2', 'decision': [{'Content-Length': '999', 'Location': '/unicode/é'}, '', 5, 307, '/unicode/é', '/unicode/é', '/unicode/é', {'Content-Length': '999'}, False, False]})
check('fixture 4', solve('/requests/' + str(N) + '/3', 308, '/', 'HEAD', 'moved', True, {}), {'request': '/requests/' + str(N) + '/3', 'decision': [{'Location': '/'}, '', 5, 308, '/', '/', '/', {}, False, False]})
check('fixture 5', solve('/requests/' + str(N) + '/4', 301, '/b', 'GET', '', False, {'Location': '/stale'}), {'request': '/requests/' + str(N) + '/4', 'decision': [{'Location': '/b'}, '', 0, 301, '/b', '/b', '/b', {'Location': '/stale'}, True, False]})
check('fixture 6', solve('/requests/' + str(N) + '/5', 302, '/a"b', 'GET', 'x', False, {'Content-Type': 'custom'}), {'request': '/requests/' + str(N) + '/5', 'decision': [{'Content-Type': 'custom', 'Location': '/a"b'}, 'x', 1, 302, '/a"b', '/a"b', '/a"b', {'Content-Type': 'custom'}, False, False]})
check('fixture 7', solve('/requests/' + str(N) + '/6', 303, '/e', 'GET', 'abc', False, {}), {'request': '/requests/' + str(N) + '/6', 'decision': [{'Location': '/e'}, 'abc', 3, 303, '/e', '/e', '/e', {}, False, True]})
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
fixture 1{'decision': [{'Location': '/a?x=1&y=2', 'X': 'v'}, 'move', 4, 302, '/a?x=1&y=2', '/a?x=1&y=2', '/a?x=1&y=2', {'X': 'v'}, False, False], 'request': '/requests/1/0'}{'decision': [{'Location': '/a?x=1&y=2', 'X': 'v'}, 'move', 4, 302, '/a?x=1&y=2', '/a?x=1&y=2', '/a?x=1&y=2', {'X': 'v'}, False, False], 'request': '/requests/1/0'}Passed
fixture 2{'decision': [{'Location': '/a#part'}, 'next', 4, 303, '/a#part', '/a#part', '/a#part', {}, False, True], 'request': '/requests/1/1'}{'decision': [{'Location': '/a#part'}, 'next', 4, 303, '/a#part', '/a#part', '/a#part', {}, False, True], 'request': '/requests/1/1'}Passed
fixture 3{'decision': [{'Content-Length': '999', 'Location': '/unicode/é'}, '', 5, 307, '/unicode/é', '/unicode/é', '/unicode/é', {'Content-Length': '999'}, False, False], 'request': '/requests/1/2'}{'decision': [{'Content-Length': '999', 'Location': '/unicode/é'}, '', 5, 307, '/unicode/é', '/unicode/é', '/unicode/é', {'Content-Length': '999'}, False, False], 'request': '/requests/1/2'}Passed
fixture 4{'decision': [{'Location': '/'}, '', 5, 308, '/', '/', '/', {}, False, False], 'request': '/requests/1/3'}{'decision': [{'Location': '/'}, '', 5, 308, '/', '/', '/', {}, False, False], 'request': '/requests/1/3'}Passed
fixture 5{'decision': [{'Location': '/b'}, '', 0, 301, '/b', '/b', '/b', {'Location': '/stale'}, True, False], 'request': '/requests/1/4'}{'decision': [{'Location': '/b'}, '', 0, 301, '/b', '/b', '/b', {'Location': '/stale'}, True, False], 'request': '/requests/1/4'}Passed
fixture 6{'decision': [{'Content-Type': 'custom', 'Location': '/a"b'}, 'x', 1, 302, '/a"b', '/a"b', '/a"b', {'Content-Type': 'custom'}, False, False], 'request': '/requests/1/5'}{'decision': [{'Content-Type': 'custom', 'Location': '/a"b'}, 'x', 1, 302, '/a"b', '/a"b', '/a"b', {'Content-Type': 'custom'}, False, False], 'request': '/requests/1/5'}Passed
fixture 7{'decision': [{'Location': '/e'}, 'abc', 3, 303, '/e', '/e', '/e', {}, False, True], 'request': '/requests/1/6'}{'decision': [{'Location': '/e'}, 'abc', 3, 303, '/e', '/e', '/e', {}, False, True], 'request': '/requests/1/6'}Passed

SHA-256 / 1af2af73c80c818158ef122cb0b5f77edbcbd0e68fd7ce143594a2897497d447

Verification & scope

Stipulated offline redirect policy, not a complete HTTP, browser, URL, cache, or security implementation. Numbered variants vary request correlation identity. 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:41:37.771657+00:00.

Case digest / 312a45b04e2dd0c07ed0ffc0124bd9dd6d8e01cdb991a964f22596d257b71c4f