can1357/oh-my-pi · error · DestinationUnavailableError

an upload command containing {file} is required

Error message

an upload command containing {file} is required

What it means

For the "command" destination, createConfiguredUploader reads the "command" option from the destination runtime config and requires it to be a non-empty string, because createCommandUploader needs a {file}-referencing template. If absent, it throws DestinationUnavailableError with this message instead of proceeding.

Source

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

 * Serving destinations deliberately return `null`; the broker selects those
 * through its separate serve-kind predicate. Registry entries known to be
 * unusable, and active entries without an implementation, fail explicitly
 * before an upload can issue a network request.
 */
export function createConfiguredUploader(
	destination: BlobDestinationId,
	config: DestinationRuntimeConfig,
): BlobUploader | null {
	const metadata: BlobDestinationMetadata = BUILTIN_BLOB_DESTINATIONS[destination];
	if (metadata.status === "incompatible" || metadata.status === "defunct") {
		const reason = metadata.reason ?? `the destination is classified as ${metadata.status}`;
		throw new DestinationUnavailableError(destination, reason);
	}

	if (destination === "command") {
		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;

View on GitHub (pinned to 9690622007)

Solutions

  1. Add a command template referencing {file}, e.g. "command": "curl -sF 'file=@{file}' https://0x0.st"
  2. Fix the key spelling so it is exactly "command" in the command destination's config object
  3. Or change images.urls.destination to a different supported destination
  4. Validate the config shape: destination and command live under images.urls

Example fix

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

Strategy: validation

Validate before calling

if (config.images?.urls?.destination === "command" && typeof config.images?.urls?.command !== "string") {
	throw new Error("destination 'command' requires images.urls.command to be set");
}

Type guard

function commandConfigComplete(c: unknown): c is { destination: "command"; command: string } {
	return typeof c === "object" && c !== null
		&& (c as { destination?: unknown }).destination === "command"
		&& typeof (c as { command?: unknown }).command === "string"
		&& (c as { command: string }).command.length > 0;
}

Try / catch

try {
	const uploader = createConfiguredUploader("command", config);
} catch (err) {
	if (err instanceof DestinationUnavailableError && err.message.includes("an upload command containing {file}")) {
		// add images.urls.command with a {file} template
	}
	throw err;
}

Prevention

When it happens

Trigger: Setting "images.urls.destination": "command" without an accompanying "images.urls.command" value; the command value is empty string, whitespace, or the config key is misspelled (e.g. "cmd") so optionString returns undefined.

Common situations: Incomplete config migration where destination was set but the command field was not; typo in the key name; the command string defined in the wrong config section.

Related errors


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