can1357/oh-my-pi · error · DestinationUnavailableError

provider-native files must use the provider file channel

Error message

provider-native files must use the provider file channel

What it means

The "provider-files" destination is not an upload destination — provider-native file handling goes through the provider's dedicated file channel. If a caller requests an uploader for it, createConfiguredUploader throws DestinationUnavailableError with this message to redirect the caller to the correct API. It is a routing guard, not a config failure.

Source

Thrown at packages/coding-agent/src/blob-broker/uploaders.ts:158

		const command = optionString(config, "command");
		if (!command) {
			throw new DestinationUnavailableError(destination, "an upload command containing {file} is required");
		}
		return createCommandUploader(command);
	}

	const uploader =
		createAnonymousUploader(destination, config) ??
		createImageHostUploader(destination, config) ??
		createCloudDriveUploader(destination, config) ??
		createObjectStorageUploader(destination, config) ??
		createSelfHostedUploader(destination, config) ??
		createLegacyUploader(destination, config) ??
		createDiscordUploader(destination, config);
	if (uploader) return uploader;

	if (destination === "provider-files") {
		throw new DestinationUnavailableError(destination, "provider-native files must use the provider file channel");
	}
	if (metadata.family === "local-serving" || metadata.family === "tunnel") return null;
	throw new DestinationUnavailableError(destination, "no built-in uploader or serving adapter is implemented");
}

/** Wrap an uploader with per-hash memoization so bytes upload at most once. */
export function memoizeUploader(
	uploader: BlobUploader,
): (hash: string, request: BlobUploadRequest) => Promise<BlobPublication | null> {
	const byHash = new Map<string, Promise<BlobPublication | null>>();
	return (hash, request) => {
		let pending = byHash.get(hash);
		if (!pending) {
			pending = uploader.upload(request).catch(error => {
				byHash.delete(hash);
				logger.warn("blob-broker: upload failed; image stays inline", {
					uploader: uploader.destination,
					error: error instanceof Error ? error.message : String(error),

View on GitHub (pinned to 9690622007)

Solutions

  1. Remove "provider-files" from images.urls.destination and use a supported destination (command, a self-hosted/anonymous/legacy/discord destination)
  2. Use the provider's file API/channel directly instead of the blob broker for provider-native files
  3. Pick a local-serving or tunnel destination if you only need a URL for shared blobs
  4. Check BUILTIN_BLOB_DESTINATIONS metadata for destinations that return null (local-serving/tunnel) vs throwing

Example fix

// before
"urls": { "destination": "provider-files" }
// after
"urls": { "destination": "command", "command": "curl -sF 'file=@{file}' https://0x0.st" }
Defensive patterns

Strategy: validation

Validate before calling

if (destination === "provider-files") {
	// route through the provider file channel instead of the blob broker
	return providerFileChannelUpload(request);
}

Type guard

function isBrokerUploadDestination(id: string): boolean {
	return id !== "provider-files";
}

Try / catch

try {
	const uploader = createConfiguredUploader(destination, config);
} catch (err) {
	if (err instanceof DestinationUnavailableError && err.message.includes("provider file channel")) {
		// switch to the provider's native file API instead of the blob broker
	}
	throw err;
}

Prevention

When it happens

Trigger: Explicitly setting "images.urls.destination": "provider-files" in config, or programmatically calling createConfiguredUploader("provider-files", config). No fallback uploader exists for this id, so the branch always throws.

Common situations: Misunderstanding the destination list and assuming provider-files is an upload target; migrating config where a previous uploads mechanism was replaced by the provider file channel; tooling that enumerates destinations and tries to instantiate each one.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/f4f33c6910faedcb. Report an issue: GitHub.