langgenius/dify · error · BaseError

UsageInvalidFlag

UsageInvalidFlag

Error message

--file value must start with @ (local file) or http(s):// (remote URL)

What it means

Thrown by `parseFileFlag` (file-flags.ts:31) when the value after `key=` is neither a local path (prefix `@`) nor an HTTP(S) URL (prefix `http://`/`https://`). The parser only supports those two transfer methods; anything else (bare relative path, `ftp://`, `file://`, `s3://`) is rejected as `usage_invalid_flag` (exit 2). Note: the throw uses `ErrorCode.UsageInvalidFlag` (the SOURCE shows `code=UsageInvalidFlag` referencing the same constant).

Source

Thrown at cli/src/commands/run/app/file-flags.ts:31

      code: ErrorCode.UsageInvalidFlag,
      message: '--file must be key=@path or key=https://url',
    })

  const varname = raw.slice(0, eqIdx)
  const value = raw.slice(eqIdx + 1)

  if (varname === '')
    throw new BaseError({
      code: ErrorCode.UsageInvalidFlag,
      message: '--file varname must not be empty',
    })

  if (value.startsWith('@')) return { varname, kind: 'local', path: value.slice(1) }

  if (value.startsWith('http://') || value.startsWith('https://'))
    return { varname, kind: 'remote', url: value }

  throw new BaseError({
    code: ErrorCode.UsageInvalidFlag,
    message: '--file value must start with @ (local file) or http(s):// (remote URL)',
  })
}

const IMAGE_EXTS = new Set(['jpg', 'jpeg', 'png', 'webp', 'gif', 'svg'])
const AUDIO_EXTS = new Set(['mp3', 'm4a', 'wav', 'amr', 'mpga'])
const VIDEO_EXTS = new Set(['mp4', 'mov', 'mpeg', 'webm'])
// Matches graphon/file/constants.py DOCUMENT_EXTENSIONS (Unstructured ETL config)
const DOCUMENT_EXTS = new Set([
  'txt',
  'markdown',
  'md',
  'mdx',
  'pdf',
  'html',
  'htm',
  'xlsx',

View on GitHub (pinned to ef8544b173)

Solutions

  1. Prefix local paths with `@`: `--file doc=@./report.pdf`.
  2. Use full `https://` URLs for remote files (e.g. presigned S3/GCS links).
  3. Download non-http(s) sources to a local file first, then upload with `@`.

Example fix

// before
$ difyctl run app <uuid> --file doc=./report.pdf
// after
$ difyctl run app <uuid> --file doc=@./report.pdf
Defensive patterns

Strategy: validation

Validate before calling

function isValidFileValue(raw: string): boolean {
  const eq = raw.indexOf('=')
  if (eq < 0) return false
  const value = raw.slice(eq + 1)
  return value.startsWith('@') ||
    value.startsWith('http://') ||
    value.startsWith('https://')
}

Type guard

type ParsedFileFlag =
  | { varname: string; kind: 'local'; path: string }
  | { varname: string; kind: 'remote'; url: string }

function isParsableFileFlag(raw: string): boolean {
  const eq = raw.indexOf('=')
  if (eq <= 0) return false
  const v = raw.slice(eq + 1)
  return v.startsWith('@') || v.startsWith('http://') || v.startsWith('https://')
}

Prevention

When it happens

Trigger: Passing `--file doc=./report.pdf` (forgot `@`), `--file doc=ftp://host/x.pdf`, `--file doc=file:///abs/path`, or `--file doc=data:...`. The value does not start with `@`, `http://`, or `https://`.

Common situations: User omits the `@` sigil thinking the path is enough; uses a `file://` URI; pastes a cloud-storage URL with an unsupported scheme; relative path without the `@` prefix.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/ed51d8737519a79b. Report an issue: GitHub.