{"record":{"id":"e579c70caa0d2c53","repo":"can1357/oh-my-pi","slug":"oauth-resource-uri-must-use-http-or-https","errorCode":null,"errorMessage":"OAuth resource URI must use http or https","messagePattern":"OAuth resource URI must use http or https","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/mcp/oauth-flow.ts","lineNumber":253,"sourceCode":"\treturn {\n\t\tpreferredPort: resolveCallbackPort(config.callbackPort, redirectUri),\n\t\tcallbackPath: resolveCallbackPath(config.callbackPath, redirectUri),\n\t\tcallbackHostname: resolveCallbackHostname(redirectUri),\n\t\tredirectUri,\n\t\tallowPortFallback,\n\t};\n}\n\nfunction resolveResourceUri(resource: string | undefined): string | undefined {\n\tconst trimmed = resource?.trim();\n\tif (!trimmed) return undefined;\n\tif (trimmed !== resource) {\n\t\tthrow new Error(\"OAuth resource URI must not include surrounding whitespace\");\n\t}\n\n\tconst parsed = new URL(trimmed);\n\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\tthrow new Error(\"OAuth resource URI must use http or https\");\n\t}\n\tif (parsed.hash) {\n\t\tthrow new Error(\"OAuth resource URI must not include a fragment\");\n\t}\n\treturn trimmed;\n}\n\ninterface ResourceIndicatorFilterOptions {\n\t/** Strip any resource URL on the same origin as the authorization server. */\n\tstripSameOriginResource?: boolean;\n}\n\n/**\n * Drop a redundant fallback resource indicator relative to {@link serverUrl}.\n *\n * Provider-advertised resource indicators are authoritative even when they are\n * origin-only (`https://gateway.example.com`) or path-scoped same-origin\n * (`https://gateway.example.com/my-service/mcp`): servers can use either form","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/mcp/oauth-flow.ts#L235-L271","documentation":"resolveResourceUri requires the RFC 8707 resource indicator to be an http or https URL. After trimming, the value is parsed with new URL and any other scheme (or an unparseable/missing scheme) is rejected, because resource indicators must be absolute web URIs that identify the protected resource on the wire.","triggerScenarios":"Setting the OAuth resource option to something like \"acme.example/mcp\" (no scheme), \"ftp://...\", \"file://...\", or a typo'd scheme, then instantiating the flow options or reading resolvedResource.","commonSituations":"Omitting the scheme assuming a bare hostname is acceptable; protocol-relative URLs (//host/path); copy-pasting a path-only value; typos in https.","solutions":["Use the full absolute URL with http:// or https:// scheme for the resource indicator","Match the scheme to how the MCP server is actually served (usually https in production, http on localhost)","Fix scheme typos before configuring"],"exampleFix":"// before\n\"resource\": \"acme.example/mcp\"\n// after\n\"resource\": \"https://acme.example/mcp\"","handlingStrategy":"validation","validationCode":"const res = config.oauth?.resource;\nif (res != null) {\n  const p = new URL(res.trim());\n  if (p.protocol !== 'http:' && p.protocol !== 'https:') {\n    throw new Error(`resource must be absolute http(s) URL, got '${res}'`);\n  }\n}","typeGuard":"function isAbsoluteHttpResource(s) {\n  try { const p = new URL(s); return p.protocol === 'http:' || p.protocol === 'https:'; }\n  catch { return false; }\n}","tryCatchPattern":"try {\n  startOAuthFlow(config);\n} catch (e) {\n  if (e.message.includes('resource URI must use http or https')) {\n    throw new Error(`Prefix oauth.resource with its scheme: '${config.oauth.resource}' -> 'https://${config.oauth.resource}'`);\n  } else throw e;\n}","preventionTips":["Always use the full absolute URL as the resource indicator, usually the MCP server base URL","Reuse the same URL as the MCP server config so they stay in sync","Parse-validate with new URL() at config load"],"tags":["oauth","configuration","validation","url"],"backgroundTag":"invalid-resource-indicator","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}