{"record":{"id":"e1537656d0aa5005","repo":"langgenius/dify","slug":"app-opts-appid-mode-missing-from-app-metadata","errorCode":null,"errorMessage":"app ${opts.appId}: mode missing from app metadata","messagePattern":"app (.+?): mode missing from app metadata","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/commands/run/app/run.ts","lineNumber":68,"sourceCode":"  } catch (err) {\n    if (err instanceof HttpClientError && err.httpStatus === 422) {\n      await meta.invalidate(opts.appId)\n      throw err.withHint(\n        'app metadata cache cleared — if the app was recently republished, run the command again',\n      )\n    }\n    throw err\n  }\n}\n\nasync function executeRun(\n  opts: RunAppOptions,\n  deps: RunAppDeps,\n  meta: AppMetaClient,\n): Promise<void> {\n  const m = await meta.get(opts.appId, [FieldInfo])\n  const mode = m.info?.mode ?? ''\n  if (mode === '') throw new Error(`app ${opts.appId}: mode missing from app metadata`)\n\n  if (mode === RUN_MODES.Workflow && opts.message !== undefined && opts.message !== '') {\n    throw new BaseError({\n      code: ErrorCode.UsageInvalidFlag,\n      message: 'workflow apps do not accept a positional message',\n      hint: 'pass workflow inputs via --inputs \\'{\"key\":\"value\"}\\'',\n    })\n  }\n\n  const inputs = await resolveInputs(opts.inputsJson, opts.inputsFile, opts.inputs)\n  if (opts.files !== undefined && opts.files.length > 0) {\n    const uploadClient = new FileUploadClient(deps.http)\n    const fileInputs = await resolveFileInputs(opts.appId, opts.files, (appId, path) =>\n      uploadClient.upload(appId, path),\n    )\n    Object.assign(inputs, fileInputs)\n  }\n  const format = opts.format ?? ''","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/cli/src/commands/run/app/run.ts#L50-L86","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Defensive check before runApp: confirm mode is present.\nconst meta = await new AppMetaClient({ apps, host, cache }).get(appId, [FieldInfo])\nconst mode = meta.info?.mode\nif (!mode) throw new Error(`app ${appId} has no mode; republish or refresh`)","typeGuard":"function hasAppMode(m: { info?: { mode?: string } } | undefined): m is { info: { mode: string } } {\n  return typeof m?.info?.mode === 'string' && m.info.mode !== ''\n}","tryCatchPattern":"try {\n  await runApp(opts, deps)\n} catch (err) {\n  if (err instanceof Error && /mode missing from app metadata/.test(err.message)) {\n    // clear cache, republish/verify the app, then retry once\n  }\n  throw err\n}","preventionTips":["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."],"tags":["cli","app-metadata","version-skew","cache","difyctl","typescript"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}