{"record":{"id":"5ed4bc1ff9100056","repo":"d2lang/d2","slug":"failed-to-decompress-w","errorCode":null,"errorMessage":"failed to decompress: %w","messagePattern":"failed to decompress: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/compression/brotli.go","lineNumber":17,"sourceCode":"// d2 uses compression for compressing large static assets when its built into WASM for d2.js\npackage compression\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/andybalholm/brotli\"\n)\n\nfunc DecompressBrotli(compressed []byte) (string, error) {\n\treader := brotli.NewReader(bytes.NewReader(compressed))\n\n\tdecompressed, err := io.ReadAll(reader)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to decompress: %w\", err)\n\t}\n\n\treturn string(decompressed), nil\n}\n","sourceCodeStart":1,"sourceCodeEnd":22,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/lib/compression/brotli.go#L1-L22","documentation":"DecompressBrotli feeds compressed bytes through a brotli reader and returns this wrapped error if io.ReadAll fails mid-stream. It indicates the input is not valid brotli data or the stream is truncated/corrupt.","triggerScenarios":"Calling DecompressBrotli with bytes that are not brotli-compressed (plain text, gzip, base64 still encoded), or a truncated brotli stream.","commonSituations":"Decoding embedded/compressed diagram links where the payload was double-encoded, corrupted in transit/storage, or produced by a different compression algorithm.","solutions":["Verify the input was compressed with brotli (CompressBrotli) and not gzip/zlib/base64-encoded again","Check the payload wasn't truncated (compare lengths/hashes with the source)","Test round-trip: compress with the same lib then decompress to isolate corruption","Wrap the call so callers see the underlying brotli error via %w for diagnosis"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if len(compressed) == 0 {\n    return errors.New(\"empty payload, not brotli data\")\n}\nif compressed[0] != 0x1b && (compressed[0]&0x01) == 0 {\n    return fmt.Errorf(\"first byte %#x does not look like brotli\", compressed[0])\n}","typeGuard":"func looksLikeBrotli(b []byte) bool {\n    // brotli streams start with WBITS; simple sanity: non-empty and not ASCII text\n    return len(b) > 0 && b[0] != '<' && b[0] != '{' && b[0] != 'H'\n}","tryCatchPattern":"out, err := compression.DecompressBrotli(data)\nif err != nil {\n    var brErr brotli.Error\n    if errors.As(err, &brErr) {\n        log.Printf(\"brotli corruption: %v\", brErr)\n    }\n    return err\n}","preventionTips":["Round-trip test payloads with CompressBrotli/DecompressBrotli at write time","Do not re-encode brotli bytes (e.g. base64) without decoding before decompression","Store payloads with integrity checks (length/hash) to detect truncation"],"tags":["compression","brotli","decoding"],"backgroundTag":"corrupt-compressed-payload","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}