ComposioHQ/composio · error · ToolFileUploadError

Unsupported upload source

Error message

Unsupported upload source

What it means

readUploadSource dispatches on the file argument's shape: Blob/File-like sources and plain strings (disk paths) are supported; anything else hits the terminal branch throwing ToolFileUploadError with reason 'unsupported-source'.

Source

Thrown at ts/packages/cli/src/services/tool-file-uploads.ts:226

  file: string | File
) => {
  if (isFileLike(file)) {
    return {
      bytes: new Uint8Array(await file.arrayBuffer()),
      fileName: file.name || `file-${Date.now()}`,
      mimeType: file.type || 'application/octet-stream',
    };
  }

  if (typeof file === 'string' && /^https?:\/\//i.test(file)) {
    return readFileFromUrl(path, file);
  }

  if (typeof file === 'string') {
    return readFileFromDisk(fs, path, file);
  }

  throw new ToolFileUploadError({
    message: 'Unsupported upload source',
    reason: 'unsupported-source',
  });
};

const uploadFile = async (params: {
  readonly fs: FileSystem.FileSystem;
  readonly path: Path.Path;
  readonly file: string | File;
  readonly toolSlug: string;
  readonly toolkitSlug: string;
  readonly client: RawComposioClient;
}) => {
  const fileData = await readUploadSource(params.fs, params.path, params.file);
  // eslint-disable-next-line no-restricted-imports -- MD5 for the presigned-upload checksum is not available in Web Crypto
  const { createHash } = await import('node:crypto');
  const md5 = createHash('md5').update(fileData.bytes).digest('hex');
  const presigned = await params.client.files.createPresignedURL({

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Pass the local file path as a plain string
  2. Pass an actual Blob/File instance (e.g. new Blob([bytes])) — wrap Node Buffers: new Blob([buffer])
  3. Do not wrap the source in an object; unwrap { path } to path

Example fix

// before
upload({ file: { path: '/tmp/a.pdf' } });
// after
upload({ file: '/tmp/a.pdf' });
// or
upload({ file: new Blob([fs.readFileSync('/tmp/a.pdf')]) });
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof file !== 'string' && !(file instanceof Blob)) throw new TypeError('file must be a path string or Blob');

Type guard

const isUploadSource = (v: unknown): v is string | Blob => typeof v === 'string' || (typeof Blob !== 'undefined' && v instanceof Blob);

Prevention

When it happens

Trigger: Passing a file argument that is neither a Blob/File nor a string — e.g. a number, a plain object like { path: '...' }, a Buffer in an environment where it isn't recognized as a Blob, or null/undefined where a value is required.

Common situations: Wrapping the path in an object ({ path }) instead of passing the string, passing a Node Buffer where a Blob is expected, or a serialization step turning the File into a plain object.

Related errors


AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28). Data as JSON: /api/errors/4c0be6d10b07a6f0. Report an issue: GitHub.