langgenius/dify · error · BaseError
UsageInvalidFlag
UsageInvalidFlag
Error message
workflow apps do not accept a positional message
What it means
Thrown by `executeRun` (run/app/run.ts:71) when the resolved app mode is `Workflow` and a positional `message` argument was also supplied (`opts.message` is a non-empty string). Workflow apps take structured `inputs`, not a free-text message, so combining them is rejected as `usage_invalid_flag` (exit 2) with a hint pointing to `--inputs`.
Source
Thrown at cli/src/commands/run/app/run.ts:71
throw err.withHint(
'app metadata cache cleared — if the app was recently republished, run the command again',
)
}
throw err
}
}
async function executeRun(
opts: RunAppOptions,
deps: RunAppDeps,
meta: AppMetaClient,
): Promise<void> {
const m = await meta.get(opts.appId, [FieldInfo])
const mode = m.info?.mode ?? ''
if (mode === '') throw new Error(`app ${opts.appId}: mode missing from app metadata`)
if (mode === RUN_MODES.Workflow && opts.message !== undefined && opts.message !== '') {
throw new BaseError({
code: ErrorCode.UsageInvalidFlag,
message: 'workflow apps do not accept a positional message',
hint: 'pass workflow inputs via --inputs \'{"key":"value"}\'',
})
}
const inputs = await resolveInputs(opts.inputsJson, opts.inputsFile, opts.inputs)
if (opts.files !== undefined && opts.files.length > 0) {
const uploadClient = new FileUploadClient(deps.http)
const fileInputs = await resolveFileInputs(opts.appId, opts.files, (appId, path) =>
uploadClient.upload(appId, path),
)
Object.assign(inputs, fileInputs)
}
const format = opts.format ?? ''
const isText = TEXT_FORMATS.has(format)
const livePrint = opts.stream === true
const runClient = new AppRunClient(deps.http)View on GitHub (pinned to ef8544b173)
Solutions
- Drop the positional message and pass workflow inputs via `--inputs '{"key":"value"}'`.
- Confirm the app type with `difyctl describe app <uuid>`; if it should accept a message, it is not a workflow app.
- Update scripts to branch on app mode before choosing message vs inputs.
Example fix
// before
$ difyctl run app <workflow-uuid> "summarize this"
// after
$ difyctl run app <workflow-uuid> --inputs '{"text":"summarize this"}' Defensive patterns
Strategy: validation
Validate before calling
// Resolve mode first; only pass a message for non-workflow apps.
const mode = await getAppMode(appId)
if (mode === 'workflow' && opts.message) {
throw new Error('workflow apps take --inputs, not a message')
} Type guard
function isWorkflowMode(mode: string): boolean {
return mode === 'workflow'
} Prevention
- Branch invocation logic on app mode: workflow → `--inputs`, chat/completion → message.
- Confirm the app type with `difyctl describe app <uuid>` before scripting.
- Never combine a positional message with workflow inputs.
When it happens
Trigger: Running `difyctl run app <workflow-uuid> "hello"` or `--message "hello"` against an app whose metadata `mode === 'workflow'`. The guard at line 70 checks mode and non-empty message.
Common situations: User reuses a chat/completion invocation pattern on a workflow app; misidentifies the app type; scripting template assumes a message arg uniformly.
Related errors
- UsageInvalidFlag
- --action required: form has multiple user actions
- usage_invalid_flag
- UsageInvalidFlag
- usage_invalid_flag
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/0349419045b45c1b.
Report an issue: GitHub.