[GH-ISSUE #6614] [Bug] empty section sharing the next offset blocks tracing #3999

Closed
opened 2026-10-31 00:45:55 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 23, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6614

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

The public trace-web-source-location CLI rejects a version 3 indexed source map with two inline sections at offset line 2, column 0 when the first section has no sources and an empty mappings string. It exits 1 with invalid_request, issue path ["source_map","path"], reason invalid_format, and Indexed section offsets must be strictly increasing. No source-location Evidence is returned. The regular-map and strictly increasing indexed controls succeed; genuinely overlapping and decreasing-offset controls remain rejected.

Reproduction

From a prepared source checkout with the compiled runtime, save the following as source-map-fixture.py outside the checkout. With Python 3 and Node.js 24 on PATH, run python3 /absolute/path/to/source-map-fixture.py from the checkout root. The script creates a disposable synthetic manifest, retained script with a matching SHA-256 and byte length, five source maps, isolated CLI state, and actual public CLI subprocesses. It retains their complete stdout/stderr and prints the fixture directory. No capture authenticity, browser, provider target or external service is required. Each case ran once per tested build, and this exact script also ran once again on the source build.

import hashlib
import json
import os
from pathlib import Path
import subprocess
import tempfile

root = Path(tempfile.mkdtemp(prefix="source-map-fixture-"))
for folder in ["files/modules", "home", "temp"]:
    (root / folder).mkdir(parents=True, exist_ok=True)
source = b"first();\nsecond();\nthird();\nfourth();\nfifth();\n"
(root / "files/modules/main.js").write_bytes(source)
manifest = {
    "capture_path": str(root / "capture.json"), "capture_sha256": "a" * 64,
    "capture_kind": "browser-scenario", "source_evidence_id": None,
    "capture_completeness": {"status": "complete", "equality_eligible": True,
                             "missing_sections": [], "truncated_sections": []},
    "output_directory": str(root),
    "analysis_input": {"input_path": str(root), "format": "directory"},
    "limitations": ["Synthetic fixture; no capture authenticity asserted."],
    "scripts": [{
        "url": "https://app.test/app.js",
        "source": {"kind": "scenario-response", "transaction_id": "fixture",
                   "request_sequence": 1, "response_sequence": 2, "status": 200},
        "content": {"state": "exported", "relative_path": "modules/main.js",
                    "layout": "isolated", "layout_reason": "fixture",
                    "sha256": hashlib.sha256(source).hexdigest(), "bytes": len(source),
                    "media_type": "text/javascript", "redacted": False,
                    "representation": "browser-decoded-response-bytes"}
    }]
}
(root / "manifest.json").write_text(json.dumps(manifest))
leaf = {"version": 3, "sources": ["b.ts"], "sourcesContent": ["B"],
        "names": [], "mappings": "AAAA"}
empty = {"version": 3, "sources": [], "names": [], "mappings": ""}
def indexed(first, next_line):
    return {"version": 3, "sections": [
        {"offset": {"line": 2, "column": 0}, "map": first},
        {"offset": {"line": next_line, "column": 0}, "map": leaf}]}
cases = {
    "regular": (leaf, 1),
    "strict": (indexed(empty, 3), 4),
    "equal-empty": (indexed(empty, 2), 3),
    "overlap": (indexed({**leaf, "mappings": "AAAA;;AAAA"}, 3), 4),
    "decreasing": (indexed(empty, 1), 2),
}
env = {"PATH": os.environ["PATH"], "HOME": str(root / "home"),
       "TMPDIR": str(root / "temp"), "XDG_CONFIG_HOME": str(root / "home/config"),
       "XDG_CACHE_HOME": str(root / "home/cache"), "REA_LOG_LEVEL": "silent"}
for name, (value, line) in cases.items():
    path = root / (name + ".map")
    path.write_text(json.dumps(value, separators=(",", ":")))
    command = ["node", "scripts/rea.mjs", "trace-web-source-location",
               str(root / "manifest.json"), "0", str(path),
               "https://app.test/app.js.map", str(line), "0", "--json"]
    result = subprocess.run(command, env=env, capture_output=True, text=True, timeout=90)
    (root / (name + ".stdout.json")).write_text(result.stdout)
    (root / (name + ".stderr.txt")).write_text(result.stderr)
    data = json.loads(result.stdout)
    normalized = data.get("normalized_result", {})
    issues = data.get("details", {}).get("issues", [])
    print(json.dumps({"case": name, "exit": result.returncode,
        "code": data.get("code"),
        "matched": normalized.get("lookup", {}).get("matched_generated_position"),
        "sources": [m.get("reported_source") for m in normalized.get("matches", [])],
        "issues": [{**i, "message": i["message"].replace(str(path), name + ".map")}
                   for i in issues], "stderr": result.stderr}))
print("Retained fixture:", root)

Expected behavior

The equal-empty fixture should return successful Evidence with lookup.matched_generated_position equal to {"line":3,"column":0} and a mapped match for b.ts, embedded content B, section path [1], and original line 1, column 0. The first section contributes no mappings, and the two starting positions are sorted without a represented overlap. Keep rejection of actual overlaps and decreasing offsets.

Impact and scope

This valid indexed-map shape cannot produce the selected original-position Evidence through tracing. The observed failure is bounded to this synthetic shape; ordinary maps and strictly increasing sections work. Real-producer frequency was not measured. No target code execution, lost input bytes, security boundary crossing or generalized outage was observed. An identity-preserving workaround was not verified; rewriting or removing a section changes the selected map bytes and therefore does not establish restoration on the original artifact.

REA version

Source baseline bcd1f95e688a2ac020a9d13f9c85e0ce321cb6b6, package metadata 6.7.0. Independently reproduced through the downloaded npm rea-agents@6.7.0 public launcher as well. The registry reports that release as latest. The extracted package used the prepared checkout's dependencies through a scratch-only link; every direct dependency version matched its published manifest exactly. This was not a fresh npm installation or packaging verification.

Runtime and platform

Node.js v24.22.1; macOS 27.0.1 arm64; locked @jridgewell/trace-mapping 0.3.31. Both actual launchers ran the owned source-map codec. The successful source-build controls reported node-v8 and a 226492416-byte V8 heap limit.

Target and artifact context

Synthetic retained JavaScript script and export-shaped manifest with correct script identity, plus small UTF-8 JSON maps containing embedded version 3 leaves. The map URL is resolution context only. The true-overlap control places the first section's final mapping at generated zero-based line 4, after the second section starts at line 3; it does not depend on equality at a mapping boundary.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

  • Expected source: REA's docs/web-source-location.md:62–70 documents inline indexed sections, and src/application/WebSourceLocationService.ts:45–47 includes that support in the public result limitations. The published ECMA-426 first-edition printable standard, section 6.1 requires sections sorted by starting position without represented overlap; it does not require distinct offsets. The current ECMA-426 DecodeIndexSourceMap algorithm, steps 9.2.8–9.2.9 and 9.2.14.6–9.2.14.7 explicitly tests lesser offsets and retains the previous last mapping only when a section contributes mappings. For this FIRST empty section, equal offsets trigger neither error. The published normative HTML host was unavailable during verification; the printed standard and current draft were read, and are distinguished here.
  • Failure source: Public CLI stdout from the fixture above. The source rejection is src/javascript/sourceMaps/SourceMapFormat.ts:147–154, which rejects a comparison result of zero before inspecting the section map; src/javascript/sourceMaps/SourceMapDecoder.ts:207–235 projects the codec format error to the observed invalid input result. src/javascript/sourceMaps/TraceSourceMap.ts:34–45 independently checks genuine mapping overlap through the leaf boundary predicate.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

Observed result summary, identical across both tested launchers:

regular:     exit 0; matched {line:1,column:0}; b.ts; embedded B
strict:      exit 0; matched {line:4,column:0}; b.ts; section_path [1]; embedded B
equal-empty: exit 1; invalid_request / invalid_format; Indexed section offsets must be strictly increasing.
overlap:     exit 1; invalid_request / invalid_format; Embedded source-map mappings overlap the following section boundary.
decreasing:  exit 1; invalid_request / invalid_format; Indexed section offsets must be strictly increasing.

All ten build-comparison CLI invocations had empty stderr and completed without cleanup_incomplete or an ownership-inspection denial. The exact inline script was subsequently executed on the source build and reproduced all five results. Successful controls produced Evidence after owned codec cleanup; the equal-empty failure was directly observed through the public CLI. No helper-only or upstream-codec acceptance result is used as the normative contract.

Typed outcome or recovery expected

Return a successful source-location Evidence record for the unchanged equal-empty map, preserving its actual map SHA-256, byte count, URL context, raw text, section-local source identity and public coordinate units. Genuine invalid input should retain a typed format failure and no partial success.

Analysis or suspected cause

Source-derived explanation: structural pre-validation equates a repeated section offset with invalid ordering before considering whether the earlier section contributes mappings. That explains the executed rejection. The exact repair was not investigated or applied; a single relaxed comparison is not established as sufficient for nested sections or every downstream representation.

Additional context

Related open #6562 is distinct after reading its canonical body: its first section maps columns 0 and 2 while the next starts at column 1, and browser collection silently clips the overlapping mapping while reporting included. Its closure requires an invalid/partial collection outcome for that actual overlap. This report requires successful tracing when the first section is empty. Either failure can remain after the other is corrected. Closed source-map reports concerning omitted optional names or external sections also do not cover this fixture, which explicitly supplies names and embeds both maps.

The decoder's advertised map/reply/row/segment/depth budgets, external-section limitation, byte identity checks, safe coordinates, source/name index validation and enclosing-section boundaries remain constraints. Equal offsets are justified here for the FIRST empty section; an empty intermediate section does not remove an earlier nonempty section's overlap. Browser collection shares structural inspection, but its runtime output and an independent MCP invocation were not exercised. No browser collection success/failure claim is needed to reproduce this trace defect.

Restoration check

Rerun the public fixture on unchanged input map bytes. The equal-empty case must exit 0 and return the expected line 3 mapping, embedded content and source identity. The regular and strictly increasing controls must retain their successful results; the true-overlap and decreasing-offset controls must retain typed invalid-format failures. Preserve cleanup verification, index/coordinate validation and existing decoder budgets; accepting every indexed map would not satisfy this check.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: A directly executed public trace refuses a bounded valid indexed-map shape instead of returning the selected source-position Evidence; unaffected controls work, and no broader outage or real-producer frequency was observed.
  • Workaround status: unverified
  • Workaround basis: No identity-preserving public recovery path was demonstrated; rewriting the indexed map would change the selected Evidence artifact's bytes and digest.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6614 ## Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ## Area Evidence, artifacts, or reconstruction ## Observed behavior The public `trace-web-source-location` CLI rejects a version 3 indexed source map with two inline sections at offset line 2, column 0 when the first section has no sources and an empty mappings string. It exits 1 with `invalid_request`, issue path `["source_map","path"]`, reason `invalid_format`, and `Indexed section offsets must be strictly increasing.` No source-location Evidence is returned. The regular-map and strictly increasing indexed controls succeed; genuinely overlapping and decreasing-offset controls remain rejected. ## Reproduction From a prepared source checkout with the compiled runtime, save the following as `source-map-fixture.py` outside the checkout. With Python 3 and Node.js 24 on PATH, run `python3 /absolute/path/to/source-map-fixture.py` from the checkout root. The script creates a disposable synthetic manifest, retained script with a matching SHA-256 and byte length, five source maps, isolated CLI state, and actual public CLI subprocesses. It retains their complete stdout/stderr and prints the fixture directory. No capture authenticity, browser, provider target or external service is required. Each case ran once per tested build, and this exact script also ran once again on the source build. ```python import hashlib import json import os from pathlib import Path import subprocess import tempfile root = Path(tempfile.mkdtemp(prefix="source-map-fixture-")) for folder in ["files/modules", "home", "temp"]: (root / folder).mkdir(parents=True, exist_ok=True) source = b"first();\nsecond();\nthird();\nfourth();\nfifth();\n" (root / "files/modules/main.js").write_bytes(source) manifest = { "capture_path": str(root / "capture.json"), "capture_sha256": "a" * 64, "capture_kind": "browser-scenario", "source_evidence_id": None, "capture_completeness": {"status": "complete", "equality_eligible": True, "missing_sections": [], "truncated_sections": []}, "output_directory": str(root), "analysis_input": {"input_path": str(root), "format": "directory"}, "limitations": ["Synthetic fixture; no capture authenticity asserted."], "scripts": [{ "url": "https://app.test/app.js", "source": {"kind": "scenario-response", "transaction_id": "fixture", "request_sequence": 1, "response_sequence": 2, "status": 200}, "content": {"state": "exported", "relative_path": "modules/main.js", "layout": "isolated", "layout_reason": "fixture", "sha256": hashlib.sha256(source).hexdigest(), "bytes": len(source), "media_type": "text/javascript", "redacted": False, "representation": "browser-decoded-response-bytes"} }] } (root / "manifest.json").write_text(json.dumps(manifest)) leaf = {"version": 3, "sources": ["b.ts"], "sourcesContent": ["B"], "names": [], "mappings": "AAAA"} empty = {"version": 3, "sources": [], "names": [], "mappings": ""} def indexed(first, next_line): return {"version": 3, "sections": [ {"offset": {"line": 2, "column": 0}, "map": first}, {"offset": {"line": next_line, "column": 0}, "map": leaf}]} cases = { "regular": (leaf, 1), "strict": (indexed(empty, 3), 4), "equal-empty": (indexed(empty, 2), 3), "overlap": (indexed({**leaf, "mappings": "AAAA;;AAAA"}, 3), 4), "decreasing": (indexed(empty, 1), 2), } env = {"PATH": os.environ["PATH"], "HOME": str(root / "home"), "TMPDIR": str(root / "temp"), "XDG_CONFIG_HOME": str(root / "home/config"), "XDG_CACHE_HOME": str(root / "home/cache"), "REA_LOG_LEVEL": "silent"} for name, (value, line) in cases.items(): path = root / (name + ".map") path.write_text(json.dumps(value, separators=(",", ":"))) command = ["node", "scripts/rea.mjs", "trace-web-source-location", str(root / "manifest.json"), "0", str(path), "https://app.test/app.js.map", str(line), "0", "--json"] result = subprocess.run(command, env=env, capture_output=True, text=True, timeout=90) (root / (name + ".stdout.json")).write_text(result.stdout) (root / (name + ".stderr.txt")).write_text(result.stderr) data = json.loads(result.stdout) normalized = data.get("normalized_result", {}) issues = data.get("details", {}).get("issues", []) print(json.dumps({"case": name, "exit": result.returncode, "code": data.get("code"), "matched": normalized.get("lookup", {}).get("matched_generated_position"), "sources": [m.get("reported_source") for m in normalized.get("matches", [])], "issues": [{**i, "message": i["message"].replace(str(path), name + ".map")} for i in issues], "stderr": result.stderr})) print("Retained fixture:", root) ``` ## Expected behavior The equal-empty fixture should return successful Evidence with `lookup.matched_generated_position` equal to `{"line":3,"column":0}` and a mapped match for `b.ts`, embedded content `B`, section path `[1]`, and original line 1, column 0. The first section contributes no mappings, and the two starting positions are sorted without a represented overlap. Keep rejection of actual overlaps and decreasing offsets. ## Impact and scope This valid indexed-map shape cannot produce the selected original-position Evidence through tracing. The observed failure is bounded to this synthetic shape; ordinary maps and strictly increasing sections work. Real-producer frequency was not measured. No target code execution, lost input bytes, security boundary crossing or generalized outage was observed. An identity-preserving workaround was not verified; rewriting or removing a section changes the selected map bytes and therefore does not establish restoration on the original artifact. ## REA version Source baseline `bcd1f95e688a2ac020a9d13f9c85e0ce321cb6b6`, package metadata 6.7.0. Independently reproduced through the downloaded npm `rea-agents@6.7.0` public launcher as well. The registry reports that release as latest. The extracted package used the prepared checkout's dependencies through a scratch-only link; every direct dependency version matched its published manifest exactly. This was not a fresh npm installation or packaging verification. ## Runtime and platform Node.js v24.22.1; macOS 27.0.1 arm64; locked `@jridgewell/trace-mapping` 0.3.31. Both actual launchers ran the owned source-map codec. The successful source-build controls reported `node-v8` and a 226492416-byte V8 heap limit. ## Target and artifact context Synthetic retained JavaScript script and export-shaped manifest with correct script identity, plus small UTF-8 JSON maps containing embedded version 3 leaves. The map URL is resolution context only. The true-overlap control places the first section's final mapping at generated zero-based line 4, after the second section starts at line 3; it does not depend on equality at a mapping boundary. ## Interface CLI ## Earliest failure stage Native analysis or reconstruction ## Relevant output or evidence - Expected source: REA's `docs/web-source-location.md:62–70` documents inline indexed sections, and `src/application/WebSourceLocationService.ts:45–47` includes that support in the public result limitations. The published [ECMA-426 first-edition printable standard, section 6.1](https://ecma-international.org/wp-content/uploads/ECMA-426_1st_edition_december_2024.pdf) requires sections sorted by starting position without represented overlap; it does not require distinct offsets. The current [ECMA-426 DecodeIndexSourceMap algorithm, steps 9.2.8–9.2.9 and 9.2.14.6–9.2.14.7](https://tc39.es/ecma426/#sec-DecodeIndexSourceMap) explicitly tests lesser offsets and retains the previous last mapping only when a section contributes mappings. For this FIRST empty section, equal offsets trigger neither error. The published normative HTML host was unavailable during verification; the printed standard and current draft were read, and are distinguished here. - Failure source: Public CLI stdout from the fixture above. The source rejection is `src/javascript/sourceMaps/SourceMapFormat.ts:147–154`, which rejects a comparison result of zero before inspecting the section map; `src/javascript/sourceMaps/SourceMapDecoder.ts:207–235` projects the codec format error to the observed invalid input result. `src/javascript/sourceMaps/TraceSourceMap.ts:34–45` independently checks genuine mapping overlap through the leaf boundary predicate. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete Observed result summary, identical across both tested launchers: ```text regular: exit 0; matched {line:1,column:0}; b.ts; embedded B strict: exit 0; matched {line:4,column:0}; b.ts; section_path [1]; embedded B equal-empty: exit 1; invalid_request / invalid_format; Indexed section offsets must be strictly increasing. overlap: exit 1; invalid_request / invalid_format; Embedded source-map mappings overlap the following section boundary. decreasing: exit 1; invalid_request / invalid_format; Indexed section offsets must be strictly increasing. ``` All ten build-comparison CLI invocations had empty stderr and completed without `cleanup_incomplete` or an ownership-inspection denial. The exact inline script was subsequently executed on the source build and reproduced all five results. Successful controls produced Evidence after owned codec cleanup; the equal-empty failure was directly observed through the public CLI. No helper-only or upstream-codec acceptance result is used as the normative contract. ## Typed outcome or recovery expected Return a successful source-location Evidence record for the unchanged equal-empty map, preserving its actual map SHA-256, byte count, URL context, raw text, section-local source identity and public coordinate units. Genuine invalid input should retain a typed format failure and no partial success. ## Analysis or suspected cause Source-derived explanation: structural pre-validation equates a repeated section offset with invalid ordering before considering whether the earlier section contributes mappings. That explains the executed rejection. The exact repair was not investigated or applied; a single relaxed comparison is not established as sufficient for nested sections or every downstream representation. ## Additional context Related open [#6562](https://github.com/morluto/rea/issues/6562) is distinct after reading its canonical body: its first section maps columns 0 and 2 while the next starts at column 1, and browser collection silently clips the overlapping mapping while reporting included. Its closure requires an invalid/partial collection outcome for that actual overlap. This report requires successful tracing when the first section is empty. Either failure can remain after the other is corrected. Closed source-map reports concerning omitted optional names or external sections also do not cover this fixture, which explicitly supplies names and embeds both maps. The decoder's advertised map/reply/row/segment/depth budgets, external-section limitation, byte identity checks, safe coordinates, source/name index validation and enclosing-section boundaries remain constraints. Equal offsets are justified here for the FIRST empty section; an empty intermediate section does not remove an earlier nonempty section's overlap. Browser collection shares structural inspection, but its runtime output and an independent MCP invocation were not exercised. No browser collection success/failure claim is needed to reproduce this trace defect. ## Restoration check Rerun the public fixture on unchanged input map bytes. The equal-empty case must exit 0 and return the expected line 3 mapping, embedded content and source identity. The regular and strictly increasing controls must retain their successful results; the true-overlap and decreasing-offset controls must retain typed invalid-format failures. Preserve cleanup verification, index/coordinate validation and existing decoder budgets; accepting every indexed map would not satisfy this check. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: A directly executed public trace refuses a bounded valid indexed-map shape instead of returning the selected source-position Evidence; unaffected controls work, and no broader outage or real-producer frequency was observed. - Workaround status: unverified - Workaround basis: No identity-preserving public recovery path was demonstrated; rewriting the indexed map would change the selected Evidence artifact's bytes and digest.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3999
No description provided.