Dify API — Troubleshooting
For auth/base URL fundamentals see the setup skill.
HTTP status & error format
Errors return JSON like:
{ "status": 400, "code": "invalid_param", "message": "..." }
| Status | Common cause | Fix |
|---|---|---|
| 400 | Bad/missing param, malformed body | Validate against GET /parameters; ensure inputs keys match the app's variables |
| 401 | Missing/invalid API key | Send Authorization: Bearer <key>; use the app key for Service API, dataset key for Knowledge API |
| 403 | Action not allowed | e.g. document_indexing — can't delete a document mid-index; wait for completed |
| 404 | Resource not found | Wrong id, or user mismatch (see below); confirm base URL has /v1 |
| 413 | Payload too large | Reduce file size; check the app's file_upload limits |
| 429 | Rate limited | Back off; honor Retry-After; see rate limits below |
| 500 | Server error | Retry with backoff; check self-hosted logs |
| 503 | Service unavailable | Model provider down or app not published; retry later |
Common pitfalls
Conversation/messages come back empty or 404
The user field is the scope key. If you create a conversation with user: "a" and then
list with user: "b", you get nothing. Use the same user string for the same person on
every call. Also note: Service API users and WebApp users are separate namespaces —
a conversation created in the WebApp is not visible via the Service API and vice-versa.
Blocking request times out (~100s)
On Dify Cloud, blocking mode is behind a ~100-second proxy timeout. Long generations or
multi-step workflows will drop the connection. Use response_mode: "streaming" for
chat UIs, long outputs, and workflows.
inputs rejected / variable errors
The inputs object must contain exactly the variables defined in the app's
user_input_form. Call GET /parameters first and send {} only if the app has no
required variables.
File upload not accepted
- Upload with
multipart/form-data(use--form), not JSON. - Include the
userform field — it scopes the file. - The file
type/extension/size must be allowed by the app'sfile_uploadconfig (GET /parameters). Reference it later with{ "transfer_method": "local_file", "upload_file_id": "<id>" }.
Audio endpoints fail
/audio-to-text and /text-to-audio require the app to have an STT / TTS model configured.
Without it you'll get a model/config error — enable the model in the app settings.
Stop endpoint does nothing
Stop only works in streaming mode, needs the task_id from a streamed event (not the
message_id / workflow_run_id), and the user must match the run's user.
Wrong key for Knowledge Base calls
Knowledge Base / Datasets endpoints use a Knowledge API key (dataset-…), not an app
key (app-…). Using the app key returns 401/403.
Rate limits
- Dify Cloud applies plan-based rate limits. Inspect response headers when present:
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset. - On 429, wait and retry with exponential backoff; honor
Retry-Afterif returned. - Self-hosted has no built-in API rate limiting (configure at your proxy/gateway).
Debugging checklist
- Base URL ends with
/v1? - Correct key type (
app-…for Service API,dataset-…for Knowledge API)? userpresent and consistent?inputsmatchGET /parameters?- Long output →
streaminginstead ofblocking? - For stop/detail → using
task_idvsworkflow_run_idcorrectly? - Reproduce with curl
-vto see status code and thecode/messagebody.