{"record":{"id":"01fb90144c2c8b98","repo":"can1357/oh-my-pi","slug":"unknown-attachment-url-in-bash-command-url","errorCode":null,"errorMessage":"Unknown attachment URL in bash command: ${url}","messagePattern":"Unknown attachment URL in bash command: (.+?)","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/bash-skill-urls.ts","lineNumber":277,"sourceCode":"\tlocalOptions?: LocalProtocolOptions,\n\tensureLocalParentDirs?: boolean,\n\tcwd?: string,\n\tsessionFile?: string,\n): Promise<string> {\n\tconst url = normalizeLocalScheme(rawUrl);\n\tconst scheme = extractScheme(url);\n\tif (!scheme) {\n\t\tthrow new ToolError(`Unsupported internal URL in bash command: ${url}`);\n\t}\n\n\tif (scheme === \"skill\") {\n\t\treturn resolveSkillUrlToPath(url, skills);\n\t}\n\n\tif (scheme === \"attachment\") {\n\t\tconst attachment = attachments.find(entry => entry.uri === url);\n\t\tif (!attachment) {\n\t\t\tthrow new ToolError(`Unknown attachment URL in bash command: ${url}`);\n\t\t}\n\t\treturn path.resolve(attachment.sourcePath);\n\t}\n\n\tif (scheme === \"local\") {\n\t\tif (!localOptions) {\n\t\t\tthrow new ToolError(\n\t\t\t\t\"Cannot resolve local:// URL in bash command: local protocol options are unavailable for this session.\",\n\t\t\t);\n\t\t}\n\t\tconst resolvedLocalPath = resolveLocalUrlToPath(url, localOptions);\n\t\tif (ensureLocalParentDirs) {\n\t\t\tawait fs.mkdir(path.dirname(resolvedLocalPath), { recursive: true });\n\t\t}\n\t\treturn resolvedLocalPath;\n\t}\n\n\tif (!internalRouter?.canHandle(url)) {","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/bash-skill-urls.ts#L259-L295","documentation":"For 'attachment://' URLs, resolveInternalUrlToPath looks up the URI in the session's known attachment list. If no entry's uri matches the requested URL, it throws this ToolError because the attachment does not exist in the current session and there is no sourcePath to resolve to.","triggerScenarios":"A bash command references attachment://<uri> but the uri is not among the ImageAttachmentEntry values captured for the session — the attachment was never added, was added in a different session, or the URI string differs (trailing slash, different id, typo).","commonSituations":"Referencing an attachment from a previous session or another agent run; hand-typing the attachment URI with the wrong id; an attachment that failed to load so it was never registered.","solutions":["List the session's current attachments and copy the exact attachment:// URI from there.","Verify the command runs in the same session where the attachment was created.","Fix typos or normalization differences in the URI (compare byte-for-byte against the registered entry.uri).","Pass the file's source path directly instead of the attachment URL if you know it."],"exampleFix":"// before\nconst cmd = `wc -c attachment://img-0042.png`; // not registered\n// after\nconst cmd = `wc -c attachment://8f3a.../screenshot.png`; // exact URI from session attachments","handlingStrategy":"validation","validationCode":"const known = new Set(attachments.map(a => a.uri));\nif (!known.has(url)) throw new Error(`Attachment not in session: ${url}`);","typeGuard":null,"tryCatchPattern":"try { await expandInternalUrls(cmd, ctx); } catch (e) { if (e instanceof ToolError && e.message.includes('Unknown attachment URL')) { /* list valid attachments and retry with correct URI */ } else throw e; }","preventionTips":["Copy attachment:// URIs exactly from the session's attachment list output.","Don't reuse attachment URIs across sessions; they are session-scoped.","Verify the attachment actually loaded before referencing it."],"tags":["bash","attachments","url-resolution"],"backgroundTag":"unknown-attachment-uri","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}