{"record":{"id":"3060b10f67fa9389","repo":"can1357/oh-my-pi","slug":"invalid-args-for-xd-url-prefix-device-name","errorCode":null,"errorMessage":"Invalid args for ${XD_URL_PREFIX}${device.name}: ${message}\\n\\n${docs()}","messagePattern":"Invalid args for (.+?)(.+?): (.+?)\\\\n\\\\n(.+?)","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/xdev.ts","lineNumber":181,"sourceCode":"\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new ToolError(\n\t\t\t`${XD_URL_PREFIX}${device.name} content must be a JSON object, got ${Array.isArray(parsed) ? \"array\" : typeof parsed}.`,\n\t\t);\n\t}\n\t// The harness only injects the intent field into top-level schemas; strip a\n\t// habitual `i` from inner args unless the wrapped schema really declares it.\n\tconst args: Record<string, unknown> = { ...(parsed as Record<string, unknown>) };\n\tif (\"i\" in args && !schemaDeclaresIntentField(toolWireSchema(device))) delete args.i;\n\ttry {\n\t\treturn validateToolArguments(device, {\n\t\t\ttype: \"toolCall\",\n\t\t\tid: toolCallId,\n\t\t\tname: device.name,\n\t\t\targuments: args,\n\t\t});\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new ToolError(`Invalid args for ${XD_URL_PREFIX}${device.name}: ${message}\\n\\n${docs()}`);\n\t}\n}\n\n/** One-line catalog summary for a mounted tool: `summary`, else first description line. */\nfunction toolSummary(inst: Tool): string {\n\tif (inst.summary) return inst.summary;\n\tconst firstLine = (inst.description ?? \"\").split(\"\\n\").find(line => line.trim().length > 0);\n\treturn firstLine?.trim() ?? inst.label ?? inst.name;\n}\n\n/** C0/C1 controls and Unicode line/paragraph separators; summaries must remain one line. */\nconst SUMMARY_CONTROL_CHARS = /[\\u0000-\\u001f\\u007f-\\u009f\\u2028\\u2029]+/g;\nconst SUMMARY_ELLIPSIS = \"…\";\nconst SUMMARY_ELLIPSIS_BYTES = Buffer.byteLength(SUMMARY_ELLIPSIS, \"utf-8\");\n\n/**\n * Bound a catalog summary for prompt rendering. External summaries are\n * third-party metadata inlined verbatim, so control characters are stripped","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/xdev.ts#L163-L199","documentation":"After parsing the JSON object, parseDeviceArgs validates it against the device's parameter schema via the wrapped tool. Any validation error thrown there is re-thrown as a single ToolError prefixed `Invalid args for xd://<device>` followed by the underlying message and the device's full docs, so the agent gets actionable schema guidance.","triggerScenarios":"Content is a valid JSON object but fails the device's schema validation — missing required fields, wrong types, unknown fields, or values violating constraints (e.g. non-enum action).","commonSituations":"An agent guesses parameter names instead of consulting the schema; hallucinated fields; wrong value type (string where number expected) after schema or device-version changes.","solutions":["Read the docs appended to the error and fix the JSON object to match the schema.","Write `?` as content to `xd://<device>` to fetch the current schema before retrying.","Add missing required fields / correct field types per the underlying validation message.","If parameter names changed, migrate to the new names (check the device docs for renames)."],"exampleFix":"// before\nwrite({ path: \"xd://browser\", content: \"{\\\"goTo\\\":\\\"https://x.com\\\"}\" })\n// after\nwrite({ path: \"xd://browser\", content: \"{\\\"action\\\":\\\"navigate\\\",\\\"url\\\":\\\"https://x.com\\\"}\" })","handlingStrategy":"try-catch","validationCode":"// validate against the device schema before writing\nconst docs = await write({ path: `xd://${device}`, content: \"?\" });\n// ensure args object keys match the documented required fields/types","typeGuard":"function argsMatchSchema(args: Record<string, unknown>, required: string[]): boolean { return required.every((k) => k in args); }","tryCatchPattern":"try { await write({ path, content: JSON.stringify(args) }); } catch (e) { if (String(e.message).startsWith(\"Invalid args for\")) { console.error(e.message); /* message includes device docs; correct args and retry */ } else throw e; }","preventionTips":["Fetch device docs (`?` content) before the first call to a device.","Only send fields defined in the device schema; no guessed names.","Match exact types (string vs number) from the schema.","Retry with corrected args using the docs appended to the error."],"tags":["validation","schema","xdev","tool-error"],"backgroundTag":"schema-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}