{"record":{"id":"e6827c9380df15c3","repo":"can1357/oh-my-pi","slug":"container","errorCode":"container","errorMessage":"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI must be a single-host absolute path.","messagePattern":"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI must be a single-host absolute path\\.","errorType":"error_code","errorClass":"AIError.AwsCredentialsError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/providers/aws-credentials.ts","lineNumber":821,"sourceCode":"\tAccessKeyId?: string;\n\tSecretAccessKey?: string;\n\tToken?: string;\n\tExpiration?: string;\n}\n\nconst ECS_TASK_CREDENTIALS_BASE_URL = new URL(\"http://169.254.170.2/\");\n\nasync function readContainerCredentials(\n\tsignal: AbortSignal | undefined,\n\tfetchImpl: FetchImpl,\n): Promise<ResolvedCredentials | undefined> {\n\tconst relativeUri = $env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI;\n\tconst fullUri = $env.AWS_CONTAINER_CREDENTIALS_FULL_URI;\n\tif (!relativeUri && !fullUri) return undefined;\n\tlet endpoint: URL;\n\tif (relativeUri) {\n\t\tif (!relativeUri.startsWith(\"/\") || relativeUri.startsWith(\"//\")) {\n\t\t\tthrow new AIError.AwsCredentialsError(\n\t\t\t\t\"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI must be a single-host absolute path.\",\n\t\t\t\t\"container\",\n\t\t\t);\n\t\t}\n\t\tendpoint = new URL(relativeUri.slice(1), ECS_TASK_CREDENTIALS_BASE_URL);\n\t} else {\n\t\ttry {\n\t\t\tendpoint = new URL(fullUri as string);\n\t\t} catch (err) {\n\t\t\tthrow new AIError.AwsCredentialsError(\n\t\t\t\t`AWS_CONTAINER_CREDENTIALS_FULL_URI is invalid: ${String(err)}`,\n\t\t\t\t\"container\",\n\t\t\t\t{ cause: err },\n\t\t\t);\n\t\t}\n\t\tif (endpoint.protocol !== \"https:\" && !isLocalOrMetadataHost(endpoint.hostname)) {\n\t\t\tthrow new AIError.AwsCredentialsError(\n\t\t\t\t\"AWS_CONTAINER_CREDENTIALS_FULL_URI must use HTTPS or a local metadata host.\",","sourceCodeStart":803,"sourceCodeEnd":839,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/providers/aws-credentials.ts#L803-L839","documentation":"ECS task credential resolution reads AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, which per the AWS contract must be a path like /v2/credentials/... that is appended to http://169.254.170.2. The library rejects values that do not start with a single \"/\" (or start with \"//\", which URL parsing would treat as protocol-relative host) so it never builds a bogus endpoint.","triggerScenarios":"resolveContainerCredentials runs because AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set, and the value is empty-of-slash, e.g. \"v2/credentials/uuid\", \"http://...\", or \"//169.254.170.2/...\".","commonSituations":"Hand-copied the full ECS agent URL into the RELATIVE var instead of the FULL_URI one; leading slash stripped by a container orchestrator template; env var interpolated with the host portion included; using credentials from an ECS task metadata endpoint copied verbatim.","solutions":["Set the value to just the path portion starting with exactly one slash, e.g. AWS_CONTAINER_CREDENTIALS_RELATIVE_URI=/v2/credentials/<uuid>.","If you have the full URL (including http://169.254.170.2), use AWS_CONTAINER_CREDENTIALS_FULL_URI instead.","Inside ECS, prefer inheriting the variable the agent injects rather than rewriting it.","Log/echo the env var in the container to see what was actually passed and fix the templating that mangled it."],"exampleFix":"// before\nAWS_CONTAINER_CREDENTIALS_RELATIVE_URI=http://169.254.170.2/v2/credentials/6d1a-...\n\n// after\nAWS_CONTAINER_CREDENTIALS_RELATIVE_URI=/v2/credentials/6d1a-...","handlingStrategy":"validation","validationCode":"function validRelativeUri(v) {\n  return typeof v === \"string\" && v.startsWith(\"/\") && !v.startsWith(\"//\");\n}\nconst rel = process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI;\nif (rel && !validRelativeUri(rel)) {\n  throw new Error(`AWS_CONTAINER_CREDENTIALS_RELATIVE_URI must start with a single '/': ${rel}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await resolveAwsCredentials();\n} catch (err) {\n  if (err instanceof AIError.AwsCredentialsError && err.code === \"container\" && /must be a single-host absolute path/.test(err.message)) {\n    logger.error(\"Fix AWS_CONTAINER_CREDENTIALS_RELATIVE_URI to a path like /v2/credentials/<id>, or use FULL_URI\");\n    throw err;\n  }\n  throw err;\n}","preventionTips":["Copy only the path portion into RELATIVE_URI; full URLs belong in FULL_URI.","Log the resolved env vars in container entrypoints to catch template mangling early.","In ECS, prefer the agent-injected value over hand-set copies.","Add a startup assertion for the env var format in task definitions that use it."],"tags":["aws","ecs","container","env-var","validation"],"backgroundTag":"invalid-env-var-format","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}