[GH-ISSUE #6631] [Bug] Signal decoding succeeds after sigrok rejects the selected channel #4015

Closed
opened 2026-10-31 00:46:04 +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/6631

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

decode_signal_recording returns successful observed Evidence for decoders: "uart:rx=NONEXISTENT:baudrate=9600" on a VCD recording whose only channel is RX. sigrok explicitly reports No channel with name "NONEXISTENT" found. but exits zero and falls back to decoding the available channel. REA preserves that diagnostic while publishing 33 annotation lines and retaining the nonexistent channel as the report's selection. The valid rx=RX control returns the same annotation text with empty diagnostics.

Reproduction

With the checkout's locked dependencies installed, Node.js 24.22.1, sigrok-cli 0.7.2 with libsigrokdecode, and REA_SIGROK_COMMAND set to its absolute executable, run this from the checkout. The observed probe used these production provider/service functions, real sigrok and real /usr/bin/prlimit; no provider or launcher was substituted. The compact recipe below is extracted from that executed matrix; it was not separately replayed.

node --import tsx --input-type=module <<'JS'
import { mkdtempSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { SigrokRecordingProvider } from './src/signals/SigrokRecordingProvider.ts';
import { SignalRecordingService } from './src/application/signals/SignalRecordingService.ts';
import { projectAnalysisError } from './src/domain/analysisErrorProjection.ts';
const root = mkdtempSync(join(tmpdir(), 'rea-signal-repro-'));
const path = join(root, 'uart.vcd');
const lines = ['$timescale 1 us $end', '$scope module logic $end',
  '$var wire 1 ! RX $end', '$upscope $end', '$enddefinitions $end', '#0', '1!'];
let tick = 1000;
for (const byte of Buffer.from('REA')) {
  for (const bit of [0, ...Array.from({length: 8}, (_, i) => (byte >> i) & 1), 1]) {
    lines.push(`#${tick}`, `${bit}!`); tick += 104;
  }
  tick += 208;
}
lines.push(`#${tick + 1000}`, '1!');
writeFileSync(path, lines.join('\n') + '\n');
const service = new SignalRecordingService(new SigrokRecordingProvider(process.env));
for (const decoders of ['uart:rx=RX:baudrate=9600', 'uart:rx=NONEXISTENT:baudrate=9600']) {
  const result = await service.decode({path, decoders, input_format: 'vcd'});
  console.log(JSON.stringify(result.ok ? {
    ok: true, selection: result.value.normalized_result.selection,
    diagnostics: result.value.normalized_result.diagnostics,
    annotations: result.value.normalized_result.annotations_text,
  } : {ok: false, error: projectAnalysisError(result.error)}));
}
await service.close();
JS

Expected behavior

An explicitly selected channel that the producer says does not exist should produce a typed selector refusal, rather than successful Evidence from fallback wiring. The recording guide requires channel names to match the recording and says REA does not guess wiring. Preserve the useful producer diagnostic and identify decoders as the field to correct. This does not request turning every warning into an error.

Impact and scope

P2: a channel-name typo returns plausible decoded traffic from a different effective selection. A caller checking success and selection can mistake the annotations for the requested wiring; reading diagnostics reveals the refusal. This occurred once in the executed matrix, with a successful valid-channel control. The verified workaround is using the actual RX channel name. Multi-channel recordings, other decoders, and public CLI/MCP transport were not tested.

REA version

Package version 6.7.0; current-main source 3ed9f4b7e4ccd5b009bfbe6cf80383165199530b. The latest published version was 6.7.0 when checked. This report executes the identified main source, not the published npm artifact.

Runtime and platform

Node.js v24.22.1; Linux x86_64 (Omarchy); sigrok-cli 0.7.2, libsigrokdecode 0.5.3, libsigrok 0.5.2; util-linux prlimit. The tools and libraries were extracted from official Arch packages into a temporary directory, with their library/decoder paths supplied through the provider environment.

Target and artifact context

Synthetic local VCD: one digital channel named RX, 1 µs timescale, 9600-baud 8N1 samples containing REA. No hardware acquisition or external target.

Interface

Other

Production application service and adapter, shared by CLI/MCP; public transports were not executed.

Earliest failure stage

Transport or result projection

Relevant output or evidence

Observed result subset from the real-tool production-service matrix:

{"name":"valid","ok":true,"diagnostics":"","output_window":{"total_lines":33,"returned_lines":33,"has_more":false}}
{"name":"missing-channel","ok":true,"decoders":"uart:rx=NONEXISTENT:baudrate=9600","diagnostics":"cli: No channel with name \"NONEXISTENT\" found.\n","output_window":{"total_lines":33,"returned_lines":33,"has_more":false}}

Both outputs begin with 1000-1105 uart-1: Start bit. They are projected from the executed matrix; the decoders field above abbreviates normalized_result.selection.decoders. No CLI/MCP, hardware, or independent decoder-semantics verification is claimed.

Typed outcome or recovery expected

invalid_request identifying decoders, retaining the channel refusal, and asking the caller to choose a channel actually present in the recording.

Analysis or suspected cause

Source-derived: the adapter skips selector-rejection interpretation whenever the producer exits zero. Its parser also does not recognize the channel diagnostic. sigrok's fallback is upstream behavior; the REA defect is treating an explicitly rejected wiring selection as successful Evidence.

Additional context

Prepared with AI assistance. NOT_ENOUGH_INFO: last known good version and broader decoder/channel reach are unknown. No source files were changed.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: A nonexistent explicit channel returned successful observed Evidence and 33 lines from fallback wiring in the real-tool service probe.
  • Workaround status: available
  • Workaround basis: The same fixture with its actual RX channel decoded successfully with empty diagnostics.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6631 ## 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 `decode_signal_recording` returns successful observed Evidence for `decoders: "uart:rx=NONEXISTENT:baudrate=9600"` on a VCD recording whose only channel is `RX`. sigrok explicitly reports `No channel with name "NONEXISTENT" found.` but exits zero and falls back to decoding the available channel. REA preserves that diagnostic while publishing 33 annotation lines and retaining the nonexistent channel as the report's selection. The valid `rx=RX` control returns the same annotation text with empty diagnostics. ## Reproduction With the checkout's locked dependencies installed, Node.js 24.22.1, sigrok-cli 0.7.2 with libsigrokdecode, and `REA_SIGROK_COMMAND` set to its absolute executable, run this from the checkout. The observed probe used these production provider/service functions, real sigrok and real `/usr/bin/prlimit`; no provider or launcher was substituted. The compact recipe below is extracted from that executed matrix; it was not separately replayed. ```sh node --import tsx --input-type=module <<'JS' import { mkdtempSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { SigrokRecordingProvider } from './src/signals/SigrokRecordingProvider.ts'; import { SignalRecordingService } from './src/application/signals/SignalRecordingService.ts'; import { projectAnalysisError } from './src/domain/analysisErrorProjection.ts'; const root = mkdtempSync(join(tmpdir(), 'rea-signal-repro-')); const path = join(root, 'uart.vcd'); const lines = ['$timescale 1 us $end', '$scope module logic $end', '$var wire 1 ! RX $end', '$upscope $end', '$enddefinitions $end', '#0', '1!']; let tick = 1000; for (const byte of Buffer.from('REA')) { for (const bit of [0, ...Array.from({length: 8}, (_, i) => (byte >> i) & 1), 1]) { lines.push(`#${tick}`, `${bit}!`); tick += 104; } tick += 208; } lines.push(`#${tick + 1000}`, '1!'); writeFileSync(path, lines.join('\n') + '\n'); const service = new SignalRecordingService(new SigrokRecordingProvider(process.env)); for (const decoders of ['uart:rx=RX:baudrate=9600', 'uart:rx=NONEXISTENT:baudrate=9600']) { const result = await service.decode({path, decoders, input_format: 'vcd'}); console.log(JSON.stringify(result.ok ? { ok: true, selection: result.value.normalized_result.selection, diagnostics: result.value.normalized_result.diagnostics, annotations: result.value.normalized_result.annotations_text, } : {ok: false, error: projectAnalysisError(result.error)})); } await service.close(); JS ``` ## Expected behavior An explicitly selected channel that the producer says does not exist should produce a typed selector refusal, rather than successful Evidence from fallback wiring. The [recording guide](https://github.com/morluto/rea/blob/3ed9f4b7e4ccd5b009bfbe6cf80383165199530b/docs/signal-recordings.md#L32-L33) requires channel names to match the recording and says REA does not guess wiring. Preserve the useful producer diagnostic and identify `decoders` as the field to correct. This does not request turning every warning into an error. ## Impact and scope P2: a channel-name typo returns plausible decoded traffic from a different effective selection. A caller checking success and selection can mistake the annotations for the requested wiring; reading diagnostics reveals the refusal. This occurred once in the executed matrix, with a successful valid-channel control. The verified workaround is using the actual `RX` channel name. Multi-channel recordings, other decoders, and public CLI/MCP transport were not tested. ## REA version Package version 6.7.0; current-main source `3ed9f4b7e4ccd5b009bfbe6cf80383165199530b`. The latest published version was 6.7.0 when checked. This report executes the identified main source, not the published npm artifact. ## Runtime and platform Node.js v24.22.1; Linux x86_64 (Omarchy); sigrok-cli 0.7.2, libsigrokdecode 0.5.3, libsigrok 0.5.2; util-linux prlimit. The tools and libraries were extracted from official Arch packages into a temporary directory, with their library/decoder paths supplied through the provider environment. ## Target and artifact context Synthetic local VCD: one digital channel named `RX`, 1 µs timescale, 9600-baud 8N1 samples containing `REA`. No hardware acquisition or external target. ## Interface Other Production application service and adapter, shared by CLI/MCP; public transports were not executed. ## Earliest failure stage Transport or result projection ## Relevant output or evidence Observed result subset from the real-tool production-service matrix: ```json {"name":"valid","ok":true,"diagnostics":"","output_window":{"total_lines":33,"returned_lines":33,"has_more":false}} {"name":"missing-channel","ok":true,"decoders":"uart:rx=NONEXISTENT:baudrate=9600","diagnostics":"cli: No channel with name \"NONEXISTENT\" found.\n","output_window":{"total_lines":33,"returned_lines":33,"has_more":false}} ``` Both outputs begin with `1000-1105 uart-1: Start bit`. They are projected from the executed matrix; the `decoders` field above abbreviates `normalized_result.selection.decoders`. No CLI/MCP, hardware, or independent decoder-semantics verification is claimed. ## Typed outcome or recovery expected `invalid_request` identifying `decoders`, retaining the channel refusal, and asking the caller to choose a channel actually present in the recording. ## Analysis or suspected cause Source-derived: [the adapter](https://github.com/morluto/rea/blob/3ed9f4b7e4ccd5b009bfbe6cf80383165199530b/src/signals/SigrokRecordingProvider.ts#L245-L267) skips selector-rejection interpretation whenever the producer exits zero. Its parser also does not recognize the channel diagnostic. sigrok's fallback is upstream behavior; the REA defect is treating an explicitly rejected wiring selection as successful Evidence. ## Additional context Prepared with AI assistance. NOT_ENOUGH_INFO: last known good version and broader decoder/channel reach are unknown. No source files were changed. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: A nonexistent explicit channel returned successful observed Evidence and 33 lines from fallback wiring in the real-tool service probe. - Workaround status: available - Workaround basis: The same fixture with its actual RX channel decoded successfully with empty diagnostics.
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#4015
No description provided.