{"record":{"id":"636ead282e59587c","repo":"can1357/oh-my-pi","slug":"unknown-uri-like-write-target-trimmed-did-yo","errorCode":null,"errorMessage":"Unknown URI-like write target '${trimmed}'. Did you mean 'xd://${missingDelimiter[1]}'? Prefix the path with './' to write it as a filesystem path.","messagePattern":"Unknown URI-like write target '(.+?)'\\. Did you mean 'xd://(.+?)'\\? Prefix the path with '\\./' to write it as a filesystem path\\.","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/write.ts","lineNumber":120,"sourceCode":"\tresolveXdevTool,\n\ttype XdevDispatch,\n\txdevActivitySummary,\n\txdevListing,\n} from \"./xdev\";\n\nconst LOOSE_HASHLINE_HEADER_RE = /^\\s*\\[[^#\\r\\n]+#[^ \\t\\r\\n]*\\]\\s*$/;\nconst EXECUTABLE_NOTICE = \"[Notice: Made executable via chmod +x]\";\nconst URI_LIKE_WRITE_PATH_RE = /^([a-z][a-z0-9+.-]*):\\/{1,2}(.*)$/i;\nconst XD_MISSING_DELIMITER_RE = /^xd\\/+(.*)$/i;\nconst XD_SCHEME_NEAR_MISSES: Record<string, true> = { dx: true, xdd: true, xdt: true };\n\nfunction assertWriteTargetAddressable(target: string, router: InternalUrlRouter): void {\n\tconst trimmed = target.trim();\n\tif (path.win32.isAbsolute(trimmed) || router.canHandle(trimmed)) return;\n\n\tconst missingDelimiter = trimmed.match(XD_MISSING_DELIMITER_RE);\n\tif (missingDelimiter) {\n\t\tthrow new ToolError(\n\t\t\t`Unknown URI-like write target '${trimmed}'. Did you mean 'xd://${missingDelimiter[1]}'? Prefix the path with './' to write it as a filesystem path.`,\n\t\t);\n\t}\n\n\tconst uriLike = trimmed.match(URI_LIKE_WRITE_PATH_RE);\n\tif (!uriLike) return;\n\n\tconst scheme = uriLike[1]!.toLowerCase();\n\t// conflict:// has no router handler but is spliced downstream by\n\t// parseConflictUri (which emits its own precise id/scope errors); let it pass.\n\tif (scheme === \"conflict\") return;\n\tconst canonicalScheme = router.getHandler(scheme) ? scheme : XD_SCHEME_NEAR_MISSES[scheme] ? \"xd\" : undefined;\n\tconst suggestion = canonicalScheme\n\t\t? ` Did you mean '${canonicalScheme}://${uriLike[2]}'?`\n\t\t: \" Tool devices use 'xd://<tool>'.\";\n\tthrow new ToolError(\n\t\t`Unknown URI-like write target '${trimmed}'.${suggestion} Prefix the path with './' to write it as a filesystem path.`,\n\t);","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/write.ts#L102-L138","documentation":"The write tool validates that its target path is either an absolute filesystem path or a routable URL. If the target looks like a URI but the scheme is missing the '//' after a colon (e.g. 'xd:foo' instead of 'xd://foo'), the tool refuses to guess and throws, telling you the exact corrected form. This exists to prevent silently creating a literal file named like a URI.","triggerScenarios":"Calling write({ path: \"xd:conflict-1\" }) or any target matching a scheme-without-delimiter pattern like 'scheme:rest' that is not win32-absolute and not router-handled.","commonSituations":"Models or scripts omitting the '//' in custom scheme URLs (xd:, conflict:) when writing; pasting URIs from docs that dropped slashes.","solutions":["Add the missing '//' after the scheme: write 'xd://<tool>' instead of 'xd:<tool>'","If you actually want a literal filesystem file, prefix the path with './' so it is treated as a relative path"],"exampleFix":"// before\nwrite({ path: \"xd:mem-1\", content: \"...\" })\n// after\nwrite({ path: \"xd://mem-1\", content: \"...\" })","handlingStrategy":"validation","validationCode":"const XD_MISSING_DELIMITER_RE = /^([a-z][a-z0-9+.-]*):(?![\\/\\/])(.+)/i;\nfunction isWriteTargetAddressable(target: string, router: { canHandle(t: string): boolean }): boolean {\n  const t = target.trim();\n  if (path.win32.isAbsolute(t) || router.canHandle(t)) return true;\n  return !XD_MISSING_DELIMITER_RE.test(t);\n}\nif (!isWriteTargetAddressable(p, router)) p = p.replace(/^([a-z][a-z0-9+.-]*):/i, \"$1://\");","typeGuard":"function isRoutableTarget(t: string, router: Router): boolean {\n  return router.canHandle(t.trim()) || path.win32.isAbsolute(t.trim());\n}","tryCatchPattern":"try {\n  await write({ path: target, content });\n} catch (e) {\n  if (e instanceof ToolError && e.message.includes(\"Unknown URI-like write target\")) {\n    target = target.replace(/^([a-z][a-z0-9+.-]*):(?!\\/\\/)/i, \"$1://\");\n    return write({ path: target, content });\n  }\n  throw e;\n}","preventionTips":["Always use the full scheme form scheme:// for tool-device targets","Prefix literal relative paths with ./ when they might look URI-like","Validate targets against the router before calling write"],"tags":["path-validation","uri","tool-error"],"backgroundTag":"invalid-uri-scheme","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}