langgenius/dify · error · NotCompletionAppError

not_completion_app

not_completion_app

Error message

Not Completion App

What it means

Raised by CompletionApi.post when the installed app's mode is not AppMode.COMPLETION. The completion-messages endpoint exclusively serves text-generation (completion) apps; chat, agent-chat, and workflow apps must use their own endpoints. Returns HTTP 400 with error_code 'not_completion_app'. This is a route/mode contract check — the app exists but was built as a different app type than the endpoint expects.

Source

Thrown at api/controllers/console/explore/completion.py:104

)
class CompletionApi(InstalledAppResource):
    @console_ns.expect(console_ns.models[CompletionMessageExplorePayload.__name__])
    @console_ns.response(200, "Success")
    @with_current_user
    @with_session
    @model_validate(CompletionMessageExplorePayload)
    def post(
        self,
        req_data: CompletionMessageExplorePayload,
        session: Session,
        current_user: Account,
        installed_app: InstalledApp,
    ):
        app_model = installed_app.app_with_session(session=session)
        if app_model is None:
            raise AppUnavailableError()
        if app_model.mode != AppMode.COMPLETION:
            raise NotCompletionAppError()

        args = req_data.model_dump(exclude_none=True)

        streaming = req_data.response_mode == "streaming"
        args["auto_generate_name"] = False

        installed_app.last_used_at = naive_utc_now()
        db.session.commit()

        try:
            response = AppGenerateService.generate(
                session=session,
                app_model=app_model,
                user=current_user,
                args=args,
                invoke_from=InvokeFrom.EXPLORE,
                streaming=streaming,
            )

View on GitHub (pinned to ef8544b173)

Solutions

  1. Route to /console/installed-apps/<id>/chat-messages instead if the app is a chat/agent-chat app.
  2. Before calling, fetch the installed app's mode and branch the endpoint accordingly.
  3. Re-open the app in Studio to confirm its current mode and update the client accordingly.
  4. If the app should be a completion app, recreate it with the completion template.

Example fix

// before: always calls completion endpoint
const url = `/console/installed-apps/${id}/completion-messages`

// after: branch by app mode
const mode = installedApp.app_mode
const url = mode === 'completion'
  ? `/console/installed-apps/${id}/completion-messages`
  : `/console/installed-apps/${id}/chat-messages`
Defensive patterns

Strategy: validation

Validate before calling

// Resolve the app mode from the installed-apps list, then choose the endpoint.
function pickEndpoint(installedApp) {
  return installedApp.app_mode === 'completion'
    ? `/console/installed-apps/${installedApp.id}/completion-messages`
    : `/console/installed-apps/${installedApp.id}/chat-messages`;
}

Type guard

function isCompletionApp(entry) {
  return entry?.app_mode === 'completion';
}

Try / catch

try {
  await postCompletion(id, payload);
} catch (err) {
  if (err.code === 'not_completion_app') {
    // switch to the chat-messages endpoint instead of retrying
    await postChat(id, payload);
  } else { throw err; }
}

Prevention

When it happens

Trigger: POST /console/installed-apps/<id>/completion-messages against an installed app whose App.mode is CHAT, AGENT_CHAT, ADVANCED_CHAT, WORKFLOW, or GENERATOR. Happens when a frontend hardcodes the completion endpoint regardless of app type, or when an app's mode was changed in Studio after installation.

Common situations: Frontend uses a single code path for all installed apps and hits the completion route for a chat app; user installed a chat-template app but the client assumes completion; app was converted from completion to chat after the installed_app_id was cached client-side.

Related errors


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