FAILURE MAP
← Case archive

FA-72046 / Error-correcting codes / Open access

RAID-6 weights disks by g to the power k plus one · case 01

Q-based rebuilds return wrong bytes.

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

ROOT CAUSE

The partial Q sum weights present disks by g^(k+1) (1-based disks).

VERIFIED REPAIR

Weight disk k by g^k, matching how Q was written.

Unsuccessful approach: Also shifting the inverse exponent keeps the reconstruction inconsistent with the stored Q.

Case contract

Recover one missing data block of a RAID-6 stripe over GF(2^8) (0x11D). data has exactly one None (else None is returned). P = XOR of data; Q = sum of g^k * D_k with g = 2 and k the 0-based disk index. Use P when it is available; otherwise rebuild D_i = (Q + sum over present k of g^k D_k) * g^(-i); if neither is available return None.

Why this case matters

Dual-parity arrays rebuild a data disk from the Q syndrome when the P disk has also failed.

1 / The failure

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

N = 1
observations = []
def solve(data, p, q):
    EXP, LOG = [0] * 512, [0] * 256
    x = 1
    for i in range(255):
        EXP[i] = EXP[i + 255] = x
        LOG[x] = i
        x <<= 1
        if x & 0x100:
            x ^= 0x11D
    def mul(a, b):
        return 0 if a == 0 or b == 0 else EXP[LOG[a] + LOG[b]]
    
    if data.count(None) != 1:
        return None
    i = data.index(None)
    if p is not None:
        x = p
        for v in data:
            if v is not None:
                x ^= v
        return x
    if q is None:
        return None
    x = q
    for k, v in enumerate(data):
        if v is not None:
            x ^= mul(EXP[k + 1], v)
    return mul(x, EXP[(255 - i) % 255])
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression [[111, null], null, 186]', [[111, None], None, 186], 228], ['regression [[61, null, 139], null, 236]', [[61, None, 139], None, 236], 237], ['control [[61, null, 139], 91, 236]', [[61, None, 139], 91, 236], 237], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222], ['control [[220, 10, null], 58, 95]', [[220, 10, None], 58, 95], 236], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73], ['control [[1, 2], null, 3]', [[1, 2], None, 3], None], ['control [[null, null], 1, 2]', [[None, None], 1, 2], None]], [['regression [[104, 202, 220, 113, null], null, 38]', [[104, 202, 220, 113, None], None, 38], 191], ['regression [[10, 11, null, 231, 194, 75], null, 1]', [[10, 11, None, 231, 194, 75], None, 1], 222], ['control [[null, null], 1, 2]', [[None, None], 1, 2], None], ['control [[4, null], null, null]', [[4, None], None, None], None], ['control [[61, null, 139], 91, 236]', [[61, None, 139], 91, 236], 237], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222], ['control [[220, 10, null], 58, 95]', [[220, 10, None], 58, 95], 236], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73]], [['regression [[220, 10, null], null, 95]', [[220, 10, None], None, 95], 236], ['regression [[68, 12, null, 209], null, 47]', [[68, 12, None, 209], None, 47], 106], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73], ['control [[1, 2], null, 3]', [[1, 2], None, 3], None], ['control [[null, null], 1, 2]', [[None, None], 1, 2], None], ['control [[4, null], null, null]', [[4, None], None, None], None], ['control [[61, null, 139], 91, 236]', [[61, None, 139], 91, 236], 237], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222]], [['regression [[114, null, 163, 119, 100, 76], null, 178]', [[114, None, 163, 119, 100, 76], None, 178], 73], ['regression [[130, 12, 210, 57, null, 52, 76], null, 198]', [[130, 12, 210, 57, None, 52, 76], None, 198], 161], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222], ['control [[220, 10, null], 58, 95]', [[220, 10, None], 58, 95], 236], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73], ['control [[1, 2], null, 3]', [[1, 2], None, 3], None], ['control [[null, null], 1, 2]', [[None, None], 1, 2], None], ['control [[4, null], null, null]', [[4, None], None, None], None]], [['regression [[null, 5], null, 7]', [[None, 5], None, 7], 13], ['regression [[111, null], null, 186]', [[111, None], None, 186], 228], ['partial-repair [[null], null, 9]', [[None], None, 9], 9], ['control [[4, null], null, null]', [[4, None], None, None], None], ['control [[61, null, 139], 91, 236]', [[61, None, 139], 91, 236], 237], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222], ['control [[220, 10, null], 58, 95]', [[220, 10, None], 58, 95], 236], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73]]]
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
regression [[111, null], null, 186]50228Failed
regression [[61, null, 139], null, 236]93237Failed
control [[61, null, 139], 91, 236]237237Passed
control [[10, 11, null, 231, 194, 75], 177, 1]222222Passed
control [[220, 10, null], 58, 95]236236Passed
control [[114, null, 163, 119, 100, 76], 199, 178]7373Passed
control [[1, 2], null, 3]NoneNonePassed
control [[null, null], 1, 2]NoneNonePassed

SHA-256 / 31c733934eab7176b92163fc8a2b1518e2d211c973fcaf26d0f75943fde96005

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(data, p, q):
    EXP, LOG = [0] * 512, [0] * 256
    x = 1
    for i in range(255):
        EXP[i] = EXP[i + 255] = x
        LOG[x] = i
        x <<= 1
        if x & 0x100:
            x ^= 0x11D
    def mul(a, b):
        return 0 if a == 0 or b == 0 else EXP[LOG[a] + LOG[b]]
    
    if data.count(None) != 1:
        return None
    i = data.index(None)
    if p is not None:
        x = p
        for v in data:
            if v is not None:
                x ^= v
        return x
    if q is None:
        return None
    x = q
    for k, v in enumerate(data):
        if v is not None:
            x ^= mul(EXP[k + 1], v)
    return mul(x, EXP[(254 - i) % 255])
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression [[111, null], null, 186]', [[111, None], None, 186], 228], ['regression [[61, null, 139], null, 236]', [[61, None, 139], None, 236], 237], ['control [[61, null, 139], 91, 236]', [[61, None, 139], 91, 236], 237], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222], ['control [[220, 10, null], 58, 95]', [[220, 10, None], 58, 95], 236], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73], ['control [[1, 2], null, 3]', [[1, 2], None, 3], None], ['control [[null, null], 1, 2]', [[None, None], 1, 2], None]], [['regression [[104, 202, 220, 113, null], null, 38]', [[104, 202, 220, 113, None], None, 38], 191], ['regression [[10, 11, null, 231, 194, 75], null, 1]', [[10, 11, None, 231, 194, 75], None, 1], 222], ['control [[null, null], 1, 2]', [[None, None], 1, 2], None], ['control [[4, null], null, null]', [[4, None], None, None], None], ['control [[61, null, 139], 91, 236]', [[61, None, 139], 91, 236], 237], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222], ['control [[220, 10, null], 58, 95]', [[220, 10, None], 58, 95], 236], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73]], [['regression [[220, 10, null], null, 95]', [[220, 10, None], None, 95], 236], ['regression [[68, 12, null, 209], null, 47]', [[68, 12, None, 209], None, 47], 106], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73], ['control [[1, 2], null, 3]', [[1, 2], None, 3], None], ['control [[null, null], 1, 2]', [[None, None], 1, 2], None], ['control [[4, null], null, null]', [[4, None], None, None], None], ['control [[61, null, 139], 91, 236]', [[61, None, 139], 91, 236], 237], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222]], [['regression [[114, null, 163, 119, 100, 76], null, 178]', [[114, None, 163, 119, 100, 76], None, 178], 73], ['regression [[130, 12, 210, 57, null, 52, 76], null, 198]', [[130, 12, 210, 57, None, 52, 76], None, 198], 161], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222], ['control [[220, 10, null], 58, 95]', [[220, 10, None], 58, 95], 236], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73], ['control [[1, 2], null, 3]', [[1, 2], None, 3], None], ['control [[null, null], 1, 2]', [[None, None], 1, 2], None], ['control [[4, null], null, null]', [[4, None], None, None], None]], [['regression [[null, 5], null, 7]', [[None, 5], None, 7], 13], ['regression [[111, null], null, 186]', [[111, None], None, 186], 228], ['partial-repair [[null], null, 9]', [[None], None, 9], 9], ['control [[4, null], null, null]', [[4, None], None, None], None], ['control [[61, null, 139], 91, 236]', [[61, None, 139], 91, 236], 237], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222], ['control [[220, 10, null], 58, 95]', [[220, 10, None], 58, 95], 236], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73]]]
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
regression [[111, null], null, 186]25228Failed
regression [[61, null, 139], null, 236]160237Failed
control [[61, null, 139], 91, 236]237237Passed
control [[10, 11, null, 231, 194, 75], 177, 1]222222Passed
control [[220, 10, null], 58, 95]236236Passed
control [[114, null, 163, 119, 100, 76], 199, 178]7373Passed
control [[1, 2], null, 3]NoneNonePassed
control [[null, null], 1, 2]NoneNonePassed

SHA-256 / 421736afac95310fae54db7911fd45912d6e90b5b3b97183d351e79a63f4ad1a

3 / The verified repair

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

N = 1
observations = []
def solve(data, p, q):
    EXP, LOG = [0] * 512, [0] * 256
    x = 1
    for i in range(255):
        EXP[i] = EXP[i + 255] = x
        LOG[x] = i
        x <<= 1
        if x & 0x100:
            x ^= 0x11D
    def mul(a, b):
        return 0 if a == 0 or b == 0 else EXP[LOG[a] + LOG[b]]
    
    if data.count(None) != 1:
        return None
    i = data.index(None)
    if p is not None:
        x = p
        for v in data:
            if v is not None:
                x ^= v
        return x
    if q is None:
        return None
    x = q
    for k, v in enumerate(data):
        if v is not None:
            x ^= mul(EXP[k], v)
    return mul(x, EXP[(255 - i) % 255])
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression [[111, null], null, 186]', [[111, None], None, 186], 228], ['regression [[61, null, 139], null, 236]', [[61, None, 139], None, 236], 237], ['control [[61, null, 139], 91, 236]', [[61, None, 139], 91, 236], 237], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222], ['control [[220, 10, null], 58, 95]', [[220, 10, None], 58, 95], 236], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73], ['control [[1, 2], null, 3]', [[1, 2], None, 3], None], ['control [[null, null], 1, 2]', [[None, None], 1, 2], None]], [['regression [[104, 202, 220, 113, null], null, 38]', [[104, 202, 220, 113, None], None, 38], 191], ['regression [[10, 11, null, 231, 194, 75], null, 1]', [[10, 11, None, 231, 194, 75], None, 1], 222], ['control [[null, null], 1, 2]', [[None, None], 1, 2], None], ['control [[4, null], null, null]', [[4, None], None, None], None], ['control [[61, null, 139], 91, 236]', [[61, None, 139], 91, 236], 237], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222], ['control [[220, 10, null], 58, 95]', [[220, 10, None], 58, 95], 236], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73]], [['regression [[220, 10, null], null, 95]', [[220, 10, None], None, 95], 236], ['regression [[68, 12, null, 209], null, 47]', [[68, 12, None, 209], None, 47], 106], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73], ['control [[1, 2], null, 3]', [[1, 2], None, 3], None], ['control [[null, null], 1, 2]', [[None, None], 1, 2], None], ['control [[4, null], null, null]', [[4, None], None, None], None], ['control [[61, null, 139], 91, 236]', [[61, None, 139], 91, 236], 237], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222]], [['regression [[114, null, 163, 119, 100, 76], null, 178]', [[114, None, 163, 119, 100, 76], None, 178], 73], ['regression [[130, 12, 210, 57, null, 52, 76], null, 198]', [[130, 12, 210, 57, None, 52, 76], None, 198], 161], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222], ['control [[220, 10, null], 58, 95]', [[220, 10, None], 58, 95], 236], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73], ['control [[1, 2], null, 3]', [[1, 2], None, 3], None], ['control [[null, null], 1, 2]', [[None, None], 1, 2], None], ['control [[4, null], null, null]', [[4, None], None, None], None]], [['regression [[null, 5], null, 7]', [[None, 5], None, 7], 13], ['regression [[111, null], null, 186]', [[111, None], None, 186], 228], ['partial-repair [[null], null, 9]', [[None], None, 9], 9], ['control [[4, null], null, null]', [[4, None], None, None], None], ['control [[61, null, 139], 91, 236]', [[61, None, 139], 91, 236], 237], ['control [[10, 11, null, 231, 194, 75], 177, 1]', [[10, 11, None, 231, 194, 75], 177, 1], 222], ['control [[220, 10, null], 58, 95]', [[220, 10, None], 58, 95], 236], ['control [[114, null, 163, 119, 100, 76], 199, 178]', [[114, None, 163, 119, 100, 76], 199, 178], 73]]]
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
regression [[111, null], null, 186]228228Passed
regression [[61, null, 139], null, 236]237237Passed
control [[61, null, 139], 91, 236]237237Passed
control [[10, 11, null, 231, 194, 75], 177, 1]222222Passed
control [[220, 10, null], 58, 95]236236Passed
control [[114, null, 163, 119, 100, 76], 199, 178]7373Passed
control [[1, 2], null, 3]NoneNonePassed
control [[null, null], 1, 2]NoneNonePassed

SHA-256 / 5169bdccd7b640e1949432d1b5993cc0b633525bf15317e06c155af6767718db

Verification & scope

A deterministic, bounded teaching model of the named code under the stated contract; not a production codec. 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:48:34.969670+00:00.

Case digest / 3fb6d3f681217a75c965973aaf7dc226dc518be7a4242f07c05e693945d1acab