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
- Route to /console/installed-apps/<id>/chat-messages instead if the app is a chat/agent-chat app.
- Before calling, fetch the installed app's mode and branch the endpoint accordingly.
- Re-open the app in Studio to confirm its current mode and update the client accordingly.
- 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
- Always read the installed app's mode before choosing the endpoint.
- Treat mode as dynamic — it can change in Studio; do not assume it on the client.
- Use a single helper that branches the URL by app_mode.
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.