can1357/oh-my-pi · error · DestinationUnavailableError
${protocol.toUpperCase()} requires options.commandBinary poi
Error message
${protocol.toUpperCase()} requires options.commandBinary pointing to curl What it means
A DestinationUnavailableError thrown when the ftp/ftps destination (non-sftp path, which shells out to curl) has no options.commandBinary configured. Because the broker does not bundle an FTP client, it requires an explicit path/binary name for curl and refuses to guess one.
Source
Thrown at packages/coding-agent/src/blob-broker/uploaders-self-hosted.ts:220
const connectionName = `blob-${username}-${host}-${port}`.replace(/[^A-Za-z0-9._-]/g, "-");
return {
destination: "ftp",
async upload(request) {
const filename = safeFileName(request);
await writeRemoteFile(
{ name: connectionName, host, username, port, ...(keyPath ? { keyPath } : {}) },
remotePath(directory, filename),
request.bytes,
{},
);
return publication("ftp", request, publicUrl(publicBase, directory, filename));
},
};
}
const binary = optionString(config, "commandBinary");
if (!binary) {
throw new DestinationUnavailableError(
"ftp",
`${protocol.toUpperCase()} requires options.commandBinary pointing to curl`,
);
}
const password = credentialString(config, "password") ?? "";
const port = optionNumber(config, "port", 21) ?? 21;
return {
destination: "ftp",
async upload(request) {
const filename = safeFileName(request);
const destinationPath = remotePath(directory, filename);
const args = [
binary,
"--fail",
"--silent",
"--show-error",
"--ftp-create-dirs",
"--upload-file",View on GitHub (pinned to 9690622007)
Solutions
- Set options.commandBinary to your curl executable, e.g. "/usr/bin/curl" or "curl" if on PATH.
- Install curl in the environment running the upload (apt-get install curl / apk add curl).
- Verify curl supports FTP (--ftp-create-dirs, --upload-file) — standard builds do; the binary is invoked with --fail --silent --show-error.
- If you actually want SFTP, set options.protocol to "sftp" instead, which uses the built-in SSH transport and needs no curl.
Example fix
// before
{ "destination": "ftp", "options": { "protocol": "ftps", "host": "ftp.example.com", "publicBaseUrl": "https://f.example.com" } }
// after
{ "destination": "ftp", "options": { "protocol": "ftps", "host": "ftp.example.com", "commandBinary": "/usr/bin/curl", "publicBaseUrl": "https://f.example.com" } } Defensive patterns
Strategy: validation
Validate before calling
if (['ftp', 'ftps'].includes(dest.options?.protocol ?? 'ftp') && !dest.options?.commandBinary) {
throw new Error('ftp/ftps destinations require options.commandBinary pointing to curl');
} Try / catch
try {
const uploader = createSelfHostedUploader('ftp', config);
} catch (err) {
if (err?.name === 'DestinationUnavailableError' && /requires options\.commandBinary/.test(err.message)) {
// install curl or set commandBinary, then re-create the destination
} else throw err;
} Prevention
- Verify the curl binary exists at deployment time (Bun.which('curl')) before accepting ftp destinations.
- Pin an absolute curl path in config for reproducibility across environments.
- Include curl in container/CI base images used for uploads.
- Prefer protocol 'sftp' (built-in SSH transport) when curl is not available.
When it happens
Trigger: Destination "ftp" with options.protocol "ftp" or "ftps" (or protocol unset resolves only for sftp — here protocol is ftp/ftps) and options.commandBinary missing, null, or empty string.
Common situations: New self-hosted FTP destinations where the curl requirement was missed; minimal containers/CI images without curl installed; users assuming a system ftp client will be used automatically.
Understand the failure class
Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.
Related errors
- Destination option protocol must be ftp, ftps, or sftp
- ${protocol.toUpperCase()} upload command exited with code ${
- the configured command binary does not exist
- No model configured
- Azure OpenAI base URL is required. Set AZURE_OPENAI_BASE_URL
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/96c192231fd56444.
Report an issue: GitHub.