Symptoms
405 Method Not Allowederror when callingDELETE /runs/crons/<cron-id>orPATCH /runs/crons/<cron-id>POST (create) and GET operations on crons work fine
Error response:
{"title":"ErrMethodNotAllowed","status":405,"error_code":405000,"message":"Method not allowed"}
Common Causes
1. Malformed Cron ID in URL
The cron ID is being passed as a dictionary or object (e.g., {'cron_id':'<uuid>'}) instead of a bare UUID string. This produces an invalid URL like:
DELETE /runs/crons/%7B'cron_id':'...'%7DFix: Pass only the UUID string directly:
# Correctawait client.crons.delete(cron_job["cron_id"])
# Incorrect — passes the whole dictawait client.crons.delete(cron_job)2. Ingress Controller or Load Balancer Blocking HTTP Methods
Many ingress controllers, load balancers, or WAFs default to allowing only GET and POST methods. This silently blocks DELETE and PATCH requests, returning a 405 before they reach the LangGraph API server.
Fix: Update your ingress controller / load balancer / WAF configuration to allow DELETE and PATCH methods through to the LangSmith Deployment deployment.
Diagnostic Steps
Check the API version:
GET <deploy-url>/info— confirms the deployment is reachable and returns version info.Test a POST operation: Try creating a cron via
POST /runs/crons— if this works but DELETE/PATCH don't, the issue is method-level filtering.Test PATCH: Run a PATCH request against the cron:
curl -X PATCH https://<deploy-url>/runs/crons/<cron-id> \ -H "Content-Type: application/json" \ -d '{"enabled": false}'If PATCH also returns 405, the ingress/proxy is almost certainly filtering HTTP methods.
Test other DELETE operations: Try
DELETE /threads/<thread-id>to confirm whether all DELETE methods are blocked or just cron-specific ones.
Related: Retaining Threads Created by Cron Jobs
By default, cron jobs use on_run_completed="delete", which removes threads after each run. To retain threads:
When creating a cron:
cron_job = await client.crons.create(
assistant_id,
schedule="27 15 * * *",
input={"messages": [{"role": "user", "content": "..."}]},
on_run_completed="keep"
)When updating an existing cron:
await client.crons.update(cron_id="<cron-id>", on_run_completed="keep")With "keep", threads accumulate over time. To manage this, you can configure a TTL (time-to-live) in your langgraph.json to auto-delete old threads. See: How to add TTLs to your application