{"record":{"id":"64d1cc5ca07ef40d","repo":"can1357/oh-my-pi","slug":"unsupported-s3-destination-destination","errorCode":null,"errorMessage":"Unsupported S3 destination: ${destination}","messagePattern":"Unsupported S3 destination: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/uploaders-object-storage.ts","lineNumber":194,"sourceCode":"\t\t\t\tregion: optionString(config, \"region\", \"garage\") ?? \"garage\",\n\t\t\t\tpathStyle: optionBoolean(config, \"pathStyle\", true) ?? true,\n\t\t\t\tpublicBaseUrl: optionString(config, \"publicBaseUrl\"),\n\t\t\t\tkeyPrefix: configuredPrefix(config),\n\t\t\t\tcacheControl: optionString(config, \"cacheControl\"),\n\t\t\t};\n\t\tcase \"backblaze-b2\": {\n\t\t\tconst region = optionString(config, \"region\", \"us-west-004\") ?? \"us-west-004\";\n\t\t\treturn {\n\t\t\t\tendpoint: endpointOption ?? `https://s3.${region}.backblazeb2.com`,\n\t\t\t\tregion,\n\t\t\t\tpathStyle: optionBoolean(config, \"pathStyle\", false) ?? false,\n\t\t\t\tpublicBaseUrl: optionString(config, \"publicBaseUrl\"),\n\t\t\t\tkeyPrefix: configuredPrefix(config),\n\t\t\t\tcacheControl: optionString(config, \"cacheControl\"),\n\t\t\t};\n\t\t}\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported S3 destination: ${destination}`);\n\t}\n}\n\nfunction createS3Uploader(destination: BlobDestinationId, config: DestinationRuntimeConfig): BlobUploader {\n\tconst defaults = s3Defaults(destination, config);\n\tconst settings: S3Settings = { ...defaults, bucket: requiredString(config, \"bucket\") };\n\tconst sessionToken = credentialString(config, \"sessionToken\");\n\tconst credentials: AwsCredentials = {\n\t\taccessKeyId: requireCredential(config, \"accessKeyId\"),\n\t\tsecretAccessKey: requireCredential(config, \"secretAccessKey\"),\n\t\t...(sessionToken ? { sessionToken } : {}),\n\t};\n\tconst request = fetchFor(config);\n\n\treturn {\n\t\tdestination,\n\t\tasync upload(uploadRequest) {\n\t\t\tconst key = objectKey(settings.keyPrefix, fileNameFor(uploadRequest));","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/uploaders-object-storage.ts#L176-L212","documentation":"s3Defaults maps a destination id to S3 endpoint defaults and throws for destination ids it does not recognize in its switch, telling you the configured destination is not a supported S3 flavor. This is a programming/config-level guard: an unknown id reached the S3 uploader factory.","triggerScenarios":"createS3Uploader is invoked with a BlobDestinationId that falls through the switch's default arm — i.e. an id that is not one of the supported S3-compatible services (aws, cloudflare-r2, wasabi, etc.).","commonSituations":"Typo in the destination type string in config; new S3-compatible provider added to config before support exists in the broker; destination id from an older config version that was renamed.","solutions":["Check the destination id for typos against the supported S3 destination list in uploaders-object-storage.ts.","Use a supported S3-compatible id, or configure the generic S3 destination with explicit endpoint/region options.","If you need a new provider, add a case to s3Defaults rather than reusing an existing id.","Migrate legacy destination ids from older config versions to their current names."],"exampleFix":"// before\n{ \"type\": \"s3\", \"provider\": \"digitalocean-spaces\" } // not handled\n// after\n{ \"type\": \"s3\", \"provider\": \"aws\", \"endpoint\": \"https://nyc3.digitaloceanspaces.com\", \"bucket\": \"images\" }","handlingStrategy":"validation","validationCode":"const S3_DESTINATIONS = new Set([\"aws\", \"cloudflare-r2\", \"wasabi\", \"minio\", \"generic-s3\"]);\nif (!S3_DESTINATIONS.has(destination)) {\n  console.warn(`'${destination}' has no S3 defaults; supply endpoint/region explicitly or pick a supported id`);\n}","typeGuard":"function isSupportedS3Destination(id: string): boolean {\n  return [\"aws\", \"cloudflare-r2\", \"wasabi\", \"minio\", \"generic-s3\"].includes(id);\n}","tryCatchPattern":"try {\n  const uploader = createS3Uploader(destination, config);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"Unsupported S3 destination\")) {\n    console.error(`Unknown S3 provider '${destination}'; check supported ids`);\n  } else throw err;\n}","preventionTips":["source destination type ids from a shared enum/constants module","validate the whole destination config against the supported-provider list at startup","when adding a new S3-compatible provider, add the s3Defaults case in the same change","grep old configs for deprecated provider ids during upgrades"],"tags":["configuration","s3","object-storage","unsupported-provider"],"backgroundTag":"unsupported-destination-type","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}