[GH-ISSUE #5980] [Bug] Kuna list_strings invalid-address errors omit structured field issues #3647

Closed
opened 2026-10-31 00:42:41 +00:00 by bsakaguchi · 0 comments
Owner

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

Before submitting

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

Area

MCP or agent integration

Observed behavior

With a Kuna-backed analysis client, MCP list_strings rejects address: "not-an-address" and address: "0x1ffffffffffffffff" with the correct invalid_request code and actionable hexadecimal-u64 message, but omits details.issues. Recovery tells the caller to correct listed fields without listing the rejected address field or a structured reason.

The sibling address_name call with the same malformed address returns details.issues: [{"path":["address"],"reason":"invalid_format"}]. A corrected list_strings request succeeds.

Reproduction

From this source revision with dependencies installed, save the following as tests/boundary/providers/kuna/kunaAddressDiagnostics.test.ts and run:

node node_modules/vitest/vitest.mjs run tests/boundary/providers/kuna/kunaAddressDiagnostics.test.ts --maxWorkers 1

This executed one focused test through production MCP registration and the real SDK in-memory transport. The repository's simulated Kuna executable and synthetic target provide the provider fixture; no real Kuna analysis was performed. The assertions below record the current missing metadata, rather than a repaired result.

import { Client, InMemoryTransport } from "@modelcontextprotocol/client";
import { expect, it } from "vitest";
import { createServer } from "../../../../src/server/createServer.js";
import { parseMcpToolError } from "../../../fixtures/mcpToolError.js";
import { session } from "./kunaSessionFixture.js";

it("observes missing list_strings address issues through MCP", async () => {
  const { open } = await session("rea-kuna-address-diagnostic-");
  const analysis = open();
  const server = createServer({ kind: "fixed", analysis });
  const client = new Client({ name: "address-diagnostic-test", version: "1" });
  const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
  try {
    await server.connect(serverTransport);
    await client.connect(clientTransport);
    for (const address of ["not-an-address", "0x1ffffffffffffffff"]) {
      const result = await client.callTool({ name: "list_strings", arguments: { address } });
      const diagnostic = parseMcpToolError(result);
      console.log(JSON.stringify({ operation: "list_strings", address, ...diagnostic }));
      expect(diagnostic.error).toMatchObject({
        code: "invalid_request",
        category: "invalid_input",
        retryable: false,
        message: "Use an explicit hexadecimal u64 string address.",
        recovery: { kind: "inspect_input_contract", operation: "list_strings" },
      });
      expect(diagnostic.error.details).toBeUndefined();
      expect(diagnostic.error.remediation.action).toContain("Correct the listed fields");
      expect(result.structuredContent).toBeUndefined();
    }
    const control = parseMcpToolError(await client.callTool({
      name: "address_name", arguments: { address: "not-an-address" },
    }));
    console.log(JSON.stringify({ operation: "address_name", ...control }));
    expect(control.error.details).toMatchObject({
      operation: "address_name", issues: [{ path: ["address"], reason: "invalid_format" }],
    });
    const corrected = await client.callTool({
      name: "list_strings", arguments: { address: "0x9999" },
    });
    expect(corrected.isError).not.toBe(true);
    expect(corrected.structuredContent).toMatchObject({ normalized_result: [] });
    console.log(JSON.stringify({ operation: "list_strings", corrected_address: "0x9999", success: true }));
  } finally {
    await client.close();
    await server.close();
    expect(await analysis.close()).toEqual({ ok: true, value: null });
  }
});

Final run: one test passed, including both invalid addresses, the sibling diagnostic control, and the successful valid-address control. The temporary test was removed after execution.

Expected behavior

Keep the existing rejection, custom message and recovery, while supplying a safe details.issues entry naming address and a meaningful reason, consistent with Kuna's address_name validation. For example, that sibling uses {"path":["address"],"reason":"invalid_format"} for the same normalizer failure.

The input issue type defines structured correction metadata, and documented MCP recovery tells callers to correct listed fields. This concerns diagnostic consistency; optional details means the current response is still schema-valid.

Impact and scope

P3: structured correction metadata is missing for these rejected addresses, while error classification and the address-specific human message remain correct. The observed workaround is to follow that message and supply an explicit hexadecimal u64 address; 0x9999 succeeded in the same session. No actual downstream client failure, valid-input analysis failure, data loss or security boundary crossing was observed. Production frequency is unknown.

MCP was executed with a simulated provider on macOS. Equivalent CLI projection is source-derived and was not separately run. No claim of real-engine analysis coverage is made.

REA version

rea-agents 6.7.0; source revision 52415975942a4b9c53a817915b313ccc404f280e.

Runtime and platform

Node.js v24.22.0; macOS 27.0.1 arm64; Vitest 5.0.3. The repository pins Node 24.18.0, which was not separately tested.

Target and artifact context

Repository Kuna session fixture with a simulated executable and synthetic x86_64 ELF target metadata. The malformed-address branches reject before the string scan; the corrected-address control uses simulated inventory output. No target execution or real analysis database.

Interface

MCP

Earliest failure stage

Request parsing or validation

Relevant output or evidence

Both invalid list_strings requests returned isError: true, no structuredContent, and this canonical JSON in text content:

{"error":{"code":"invalid_request","category":"invalid_input","message":"Use an explicit hexadecimal u64 string address.","retryable":false,"remediation":{"action":"Read the declared input schema or CLI usage for list_strings; if using MCP and the catalog may be stale, call tools/list. Correct the listed fields, then retry. Do not repeat the unchanged call."},"recovery":{"kind":"inspect_input_contract","operation":"list_strings"}}}

There is no details property. The address_name control returned the same error classification with:

{"operation":"address_name","issues":[{"path":["address"],"reason":"invalid_format"}]}

The valid list_strings control returned success with normalized_result: [] for the unmatched but well-formed address 0x9999.

Typed outcome or recovery expected

invalid_request / invalid_input, retryable: false, and inspect_input_contract for list_strings, with details.issues identifying address. Keep rejecting both invalid examples and preserve the current custom message. No requirement to echo the rejected value or distinguish overflow from format failure is necessary for this report.

Analysis or suspected cause

Source-derived: the list_strings contract uses an optional string address, so the SDK admits both strings. KunaStringQueries.execute rejects the normalizer failure but constructs AnalysisInputError without its issue argument. The constructor defaults issues to empty, and the projector only emits input details for nonempty issues.

The producer never populates the issue metadata; this is not loss of an already-populated list during MCP delivery.

Additional context

Open and closed issue/PR searches found no matching Kuna address-diagnostic report. #5834 concerns doctor remediation for rejected environment settings, whose setting details are already present. #5759, #5950, #5971, #3865 and closed #2180 concern separate Rizin, native-matching, Android, Electron and browser/Inspector validation producers; changing those branches does not repair this one. Kuna cleanup/operation-attribution reports #4693, #4689 and #4631 also concern different contracts.

Fetched upstream main 25e1a24a3ed3671a0148757555f18d16c29d936a retains the same relevant validation and input-issue projection branches. That newer revision was inspected, not executed. No last-known-good version or introducing commit was established.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5980 ### 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 MCP or agent integration ### Observed behavior With a Kuna-backed analysis client, MCP `list_strings` rejects `address: "not-an-address"` and `address: "0x1ffffffffffffffff"` with the correct `invalid_request` code and actionable hexadecimal-u64 message, but omits `details.issues`. Recovery tells the caller to correct listed fields without listing the rejected `address` field or a structured reason. The sibling `address_name` call with the same malformed address returns `details.issues: [{"path":["address"],"reason":"invalid_format"}]`. A corrected `list_strings` request succeeds. ### Reproduction From this source revision with dependencies installed, save the following as `tests/boundary/providers/kuna/kunaAddressDiagnostics.test.ts` and run: ```sh node node_modules/vitest/vitest.mjs run tests/boundary/providers/kuna/kunaAddressDiagnostics.test.ts --maxWorkers 1 ``` This executed one focused test through production MCP registration and the real SDK in-memory transport. The repository's simulated Kuna executable and synthetic target provide the provider fixture; no real Kuna analysis was performed. The assertions below record the current missing metadata, rather than a repaired result. ```ts import { Client, InMemoryTransport } from "@modelcontextprotocol/client"; import { expect, it } from "vitest"; import { createServer } from "../../../../src/server/createServer.js"; import { parseMcpToolError } from "../../../fixtures/mcpToolError.js"; import { session } from "./kunaSessionFixture.js"; it("observes missing list_strings address issues through MCP", async () => { const { open } = await session("rea-kuna-address-diagnostic-"); const analysis = open(); const server = createServer({ kind: "fixed", analysis }); const client = new Client({ name: "address-diagnostic-test", version: "1" }); const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); try { await server.connect(serverTransport); await client.connect(clientTransport); for (const address of ["not-an-address", "0x1ffffffffffffffff"]) { const result = await client.callTool({ name: "list_strings", arguments: { address } }); const diagnostic = parseMcpToolError(result); console.log(JSON.stringify({ operation: "list_strings", address, ...diagnostic })); expect(diagnostic.error).toMatchObject({ code: "invalid_request", category: "invalid_input", retryable: false, message: "Use an explicit hexadecimal u64 string address.", recovery: { kind: "inspect_input_contract", operation: "list_strings" }, }); expect(diagnostic.error.details).toBeUndefined(); expect(diagnostic.error.remediation.action).toContain("Correct the listed fields"); expect(result.structuredContent).toBeUndefined(); } const control = parseMcpToolError(await client.callTool({ name: "address_name", arguments: { address: "not-an-address" }, })); console.log(JSON.stringify({ operation: "address_name", ...control })); expect(control.error.details).toMatchObject({ operation: "address_name", issues: [{ path: ["address"], reason: "invalid_format" }], }); const corrected = await client.callTool({ name: "list_strings", arguments: { address: "0x9999" }, }); expect(corrected.isError).not.toBe(true); expect(corrected.structuredContent).toMatchObject({ normalized_result: [] }); console.log(JSON.stringify({ operation: "list_strings", corrected_address: "0x9999", success: true })); } finally { await client.close(); await server.close(); expect(await analysis.close()).toEqual({ ok: true, value: null }); } }); ``` Final run: one test passed, including both invalid addresses, the sibling diagnostic control, and the successful valid-address control. The temporary test was removed after execution. ### Expected behavior Keep the existing rejection, custom message and recovery, while supplying a safe `details.issues` entry naming `address` and a meaningful reason, consistent with [Kuna's address_name validation](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/kuna/KunaSessionClient.ts#L902-L920). For example, that sibling uses `{"path":["address"],"reason":"invalid_format"}` for the same normalizer failure. The [input issue type](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/analysisErrorCore.ts#L79-L94) defines structured correction metadata, and [documented MCP recovery](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/docs/mcp-contracts.md#L91-L116) tells callers to correct listed fields. This concerns diagnostic consistency; optional `details` means the current response is still schema-valid. ### Impact and scope P3: structured correction metadata is missing for these rejected addresses, while error classification and the address-specific human message remain correct. The observed workaround is to follow that message and supply an explicit hexadecimal u64 address; `0x9999` succeeded in the same session. No actual downstream client failure, valid-input analysis failure, data loss or security boundary crossing was observed. Production frequency is unknown. MCP was executed with a simulated provider on macOS. Equivalent CLI projection is source-derived and was not separately run. No claim of real-engine analysis coverage is made. ### REA version `rea-agents` 6.7.0; source revision `52415975942a4b9c53a817915b313ccc404f280e`. ### Runtime and platform Node.js v24.22.0; macOS 27.0.1 arm64; Vitest 5.0.3. The repository pins Node 24.18.0, which was not separately tested. ### Target and artifact context Repository Kuna session fixture with a simulated executable and synthetic x86_64 ELF target metadata. The malformed-address branches reject before the string scan; the corrected-address control uses simulated inventory output. No target execution or real analysis database. ### Interface MCP ### Earliest failure stage Request parsing or validation ### Relevant output or evidence Both invalid `list_strings` requests returned `isError: true`, no `structuredContent`, and this canonical JSON in text content: ```json {"error":{"code":"invalid_request","category":"invalid_input","message":"Use an explicit hexadecimal u64 string address.","retryable":false,"remediation":{"action":"Read the declared input schema or CLI usage for list_strings; if using MCP and the catalog may be stale, call tools/list. Correct the listed fields, then retry. Do not repeat the unchanged call."},"recovery":{"kind":"inspect_input_contract","operation":"list_strings"}}} ``` There is no `details` property. The `address_name` control returned the same error classification with: ```json {"operation":"address_name","issues":[{"path":["address"],"reason":"invalid_format"}]} ``` The valid `list_strings` control returned success with `normalized_result: []` for the unmatched but well-formed address `0x9999`. ### Typed outcome or recovery expected `invalid_request` / `invalid_input`, `retryable: false`, and `inspect_input_contract` for `list_strings`, with `details.issues` identifying `address`. Keep rejecting both invalid examples and preserve the current custom message. No requirement to echo the rejected value or distinguish overflow from format failure is necessary for this report. ### Analysis or suspected cause Source-derived: [the list_strings contract](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/contracts/officialToolContracts.ts#L131-L138) uses [an optional string address](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/contracts/toolContractHelpers.ts#L13-L18), so the SDK admits both strings. [KunaStringQueries.execute](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/kuna/KunaStringQueries.ts#L57-L70) rejects the normalizer failure but constructs `AnalysisInputError` without its issue argument. The [constructor defaults issues to empty](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/analysisErrorCore.ts#L64-L76), and [the projector only emits input details for nonempty issues](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/analysisErrorProjection.ts#L333-L344). The producer never populates the issue metadata; this is not loss of an already-populated list during MCP delivery. ### Additional context Open and closed issue/PR searches found no matching Kuna address-diagnostic report. #5834 concerns doctor remediation for rejected environment settings, whose setting details are already present. #5759, #5950, #5971, #3865 and closed #2180 concern separate Rizin, native-matching, Android, Electron and browser/Inspector validation producers; changing those branches does not repair this one. Kuna cleanup/operation-attribution reports #4693, #4689 and #4631 also concern different contracts. Fetched upstream main `25e1a24a3ed3671a0148757555f18d16c29d936a` retains the same relevant validation and input-issue projection branches. That newer revision was inspected, not executed. No last-known-good version or introducing commit was established.
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#3647
No description provided.