langgenius/dify · error · Error
app ${opts.appId}: mode missing from app metadata
Error message
app ${opts.appId}: mode missing from app metadata What it means
Thrown by `executeRun` (run/app/run.ts:68) as a plain `Error` (no code → exit 1) when the app metadata fetch (`meta.get(appId, [FieldInfo])`) returns an object whose `info?.mode` is empty/undefined. The CLI cannot pick a run strategy without knowing the app mode (workflow vs chat vs completion), so it aborts. This is a data/state defect, not a usage error.
Source
Thrown at cli/src/commands/run/app/run.ts:68
} catch (err) {
if (err instanceof HttpClientError && err.httpStatus === 422) {
await meta.invalidate(opts.appId)
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 ?? ''View on GitHub (pinned to ef8544b173)
Solutions
- Bypass the cache: re-run with the describe/run refresh flag (`--refresh`) or clear the app-info cache.
- Verify the app is fully published and has a mode via the console or `GET /v1/apps/{id}`.
- If version skew is suspected, align the CLI version with the Dify server release.
- If the issue persists, inspect the raw metadata response to confirm `mode` is genuinely absent.
Defensive patterns
Strategy: try-catch
Validate before calling
// Defensive check before runApp: confirm mode is present.
const meta = await new AppMetaClient({ apps, host, cache }).get(appId, [FieldInfo])
const mode = meta.info?.mode
if (!mode) throw new Error(`app ${appId} has no mode; republish or refresh`) Type guard
function hasAppMode(m: { info?: { mode?: string } } | undefined): m is { info: { mode: string } } {
return typeof m?.info?.mode === 'string' && m.info.mode !== ''
} Try / catch
try {
await runApp(opts, deps)
} catch (err) {
if (err instanceof Error && /mode missing from app metadata/.test(err.message)) {
// clear cache, republish/verify the app, then retry once
}
throw err
} Prevention
- Ensure the app is fully published before invoking run.
- Keep CLI and Dify server versions aligned to avoid schema drift.
- Use `--refresh` to bypass a stale metadata cache.
- Inspect raw metadata when the error recurs to confirm the field is absent.
When it happens
Trigger: The Dify server returns app metadata without a `mode` field — possible with a partially provisioned app, a malformed cache entry, an app in an incomplete state, or API version skew where the mode field was renamed/removed. The cached `AppInfoCache` could also hold a stale entry missing the field.
Common situations: App was created via API but not fully published; CLI/server version mismatch where the mode field moved; corrupted cache; the app is a deleted/draft artifact; a proxy stripped fields.
Related errors
- usage_invalid_flag
- --action required: form has multiple user actions
- usage_invalid_flag
- UsageInvalidFlag
- Unknown
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/e1537656d0aa5005.
Report an issue: GitHub.