{"record":{"id":"f611e9c9ebfa3b0c","repo":"langgenius/dify","slug":"completion-request-error-f611e9","errorCode":"completion_request_error","errorMessage":"Completion request failed.","messagePattern":"Completion request failed\\.","errorType":"console","errorClass":"CompletionRequestError","httpStatus":400,"severity":"error","filePath":"api/controllers/console/explore/audio.py","lineNumber":89,"sourceCode":"            raise AppUnavailableError()\n        except NoAudioUploadedServiceError:\n            raise NoAudioUploadedError()\n        except AudioTooLargeServiceError as e:\n            raise AudioTooLargeError(str(e))\n        except UnsupportedAudioTypeServiceError:\n            raise UnsupportedAudioTypeError()\n        except ProviderNotSupportSpeechToTextServiceError:\n            raise ProviderNotSupportSpeechToTextError()\n        except SpeechToTextDisabledServiceError:\n            raise SpeechToTextDisabledError()\n        except ProviderTokenNotInitError as ex:\n            raise ProviderNotInitializeError(ex.description)\n        except QuotaExceededError:\n            raise ProviderQuotaExceededError()\n        except ModelCurrentlyNotSupportError:\n            raise ProviderModelCurrentlyNotSupportError()\n        except InvokeError as e:\n            raise CompletionRequestError(e.description)\n        except ValueError as e:\n            raise e\n        except Exception as e:\n            logger.exception(\"internal server error.\")\n            raise InternalServerError()\n\n\n@console_ns.route(\n    \"/installed-apps/<uuid:installed_app_id>/text-to-audio\",\n    endpoint=\"installed_app_text\",\n)\nclass ChatTextApi(InstalledAppResource):\n    @console_ns.expect(console_ns.models[TextToAudioPayload.__name__])\n    @console_ns.response(200, \"Success\", console_ns.models[AudioBinaryResponse.__name__])\n    @model_validate(TextToAudioPayload)\n    def post(self, req_data: TextToAudioPayload, installed_app: InstalledApp):\n        app_model = installed_app.app_with_session(session=db.session())\n        if app_model is None:","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/explore/audio.py#L71-L107","documentation":"HTTP 400 CompletionRequestError, raised by the STT endpoint. The model runtime raised InvokeError during the speech2text call. The controller wraps the upstream error description into this generic 'Completion request failed.' error. InvokeError is the graphon model_runtime base for provider-side invocation failures (auth, rate limit, bad request, server error, content filter, etc.).","triggerScenarios":"POST /console/explore/installed-apps/{id}/audio-to-text where the speech2text provider accepted the request at the Dify layer but returned an error during invocation: 4xx/5xx from the provider, malformed audio payload the provider rejects, rate-limited by the provider, content-policy rejection, or transient provider outage.","commonSituations":"Provider rate limit hit; audio bytes valid by MIME but corrupt/truncated so the provider fails to decode; provider temporary 5xx; API key valid at config time but later revoked (surfaces as InvokeError rather than ProviderTokenNotInitError); network blip between Dify and provider.","solutions":["Inspect server logs: the caught InvokeError's description (e.description) and the logger.exception trace identify the upstream cause.","If rate-limited, back off and retry with exponential jitter.","If the audio is corrupt, re-record/re-encode and resend.","If the provider is down, retry shortly or fail over to another configured STT provider.","If the key was revoked, re-enter credentials (see error 683)."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"async function transcribe(file, attempt = 0) {\n  try { return await postAudio(file) }\n  catch (e) {\n    if (e.code === 400 && e.error_code === 'completion_request_error' && attempt < 2 && isTransient(e))\n      return await sleep(2 ** attempt * 500).then(() => transcribe(file, attempt + 1))\n    throw e\n  }\n}","preventionTips":["Inspect e.description / server logs to distinguish rate-limit vs corrupt-audio vs outage.","Back off with jitter on rate-limit; re-encode on corrupt-audio; fail over on outage.","Keep payloads small and well-formed to reduce provider-side rejections."],"tags":["audio","stt","model-provider","invoke","http-400"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}