nexu-io/open-design · warning · Error
unsupported resource URI: ${uri}
Error message
unsupported resource URI: ${uri} What it means
The read_resource handler in mcp.ts accepts only od:// URIs of two shapes: od://skills/<id>/<path> and od://design-systems/<id>/<path> (plus an earlier od://active branch). Anything not matching the regex ^od://(skills|design-systems)/([^/]+)/(.+)$ throws.
Source
Thrown at apps/daemon/src/mcp.ts:1857
if (uri === 'od://focus/active') {
const result = await daemonTarget.call('read_resource', {}, async (baseUrl) =>
ok(await getJson<ActiveContext>(`${baseUrl}/api/active`)),
);
if (result.isError === true) throw new Error(result.content[0]?.text);
const data = parseMcpResult(result);
return {
contents: [
{
uri,
mimeType: 'application/json',
text: JSON.stringify(data, null, 2),
},
],
};
}
const m = String(uri || '').match(/^od:\/\/(skills|design-systems)\/([^/]+)\/(.+)$/);
if (!m) {
throw new Error(`unsupported resource URI: ${uri}`);
}
const [, kind, id] = m as [string, 'skills' | 'design-systems', string, string];
const route = kind === 'skills' ? 'skills' : 'design-systems';
const result = await daemonTarget.call('read_resource', {}, async (baseUrl) =>
ok(await getJson<ResourcePayload>(
`${baseUrl}/api/${route}/${encodeURIComponent(decodeURIComponent(id))}`,
)),
);
if (result.isError === true) throw new Error(result.content[0]?.text);
const data = parseMcpResult(result) as ResourcePayload | null;
const text =
data?.skill?.body ??
data?.skill?.content ??
data?.designSystem?.body ??
data?.designSystem?.content ??
data?.body ??
data?.content ??
'';View on GitHub (pinned to 5be4028344)
Solutions
- Use od://skills/<id>/<path> or od://design-systems/<id>/<path>.
- For active context use od://active.
- Ensure both the id and the trailing path segment are present.
Example fix
// before
read_resource('https://example.com/skills/foo')
// after
read_resource('od://skills/foo/SKILL.md') Defensive patterns
Strategy: type-guard
Validate before calling
const RE = /^od:\/\/(skills|design-systems)\/([^/]+)\/(.+)$/;
if (uri !== 'od://active' && !RE.test(uri)) {
throw new Error(`unsupported resource URI: ${uri}`);
} Type guard
function isOdResourceUri(u: unknown): boolean {
return typeof u === 'string'
&& (u === 'od://active'
|| /^od:\/\/(skills|design-systems)\/([^/]+)\/(.+)$/.test(u));
} Prevention
- Build od:// URIs from known skills or design-system ids.
- Reject foreign schemes before calling read_resource.
- Always include the id and the trailing path segment.
When it happens
Trigger: A client requests a non-od:// URI; a malformed od:// URI; an od:// kind other than skills or design-systems; a URI missing the id or trailing path segment.
Common situations: An external agent enumerated resources from elsewhere and tried to read them here; the URI was truncated.
Related errors
- codex mcp add failed: ${failureDetail(result)}
- codex mcp remove failed: ${failureDetail(result)}
- existing config at ${where} is not valid JSON: ${err instanc
- existing config at ${where} is not a JSON object
- The registered Open Design runtime is unavailable and cannot
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/8cb1ff8079bdca6d.
Report an issue: GitHub.