--- name: runpod-serverless-template description: Update RunPod serverless endpoint templates via GraphQL API. Query endpoints, update Docker images, env vars, and configuration. tags: [runpod, serverless, graphql, gpu, deployment] --- # RunPod Serverless Template Management via GraphQL ## When to Use - Updating a RunPod serverless endpoint's Docker image, env vars, or config - Querying endpoint/template details - Debugging worker launch failures (exit codes, missing files) ## API Endpoint ``` POST https://api.runpod.io/graphql Authorization: Bearer Content-Type: application/json ``` ## Query Endpoints with Full Detail ```graphql { myself { endpoints { id name templateId gpuIds workersMin workersMax idleTimeout env { key value } template { id name imageName dockerArgs env { key value } startJupyter startSsh } } } } ``` ## Update Template (saveTemplate) ```graphql mutation { saveTemplate(input: { id: "" name: "Template Name" imageName: "dockerhub-user/image:tag" dockerArgs: "" containerDiskInGb: 20 volumeInGb: 0 startJupyter: false startSsh: false isServerless: true env: [ { key: "KEY", value: "VALUE" } ] }) { id name imageName dockerArgs } } ``` ## Pitfalls 1. **Mutation type name**: It's `saveTemplate`, NOT `updateTemplate`. The input type is `SaveTemplateInput`. 2. **Required fields**: `containerDiskInGb` (Int!) and `volumeInGb` (Int!) and `env` ([EnvironmentVariableInput]!) are ALL required even if you're not changing them. Omitting any causes validation errors. 3. **volumeInGb quirk**: Serverless templates "don't support" volumeInGb but the field is still required. Use `volumeInGb: 0` to satisfy validation without attaching a volume. 4. **Shell escaping**: Write the JSON payload to a temp file and use `curl -d @/tmp/payload.json` to avoid shell escaping hell with nested quotes in GraphQL. 5. **dockerArgs**: When using a custom Docker image with a proper CMD/ENTRYPOINT, set `dockerArgs: ""` (empty string) so the image's own CMD is used. Non-empty dockerArgs override the image CMD. 6. **Common failure**: If workers exit with code 2 and logs show "No such file or directory" for a handler path, the dockerArgs likely contain a `git clone || true` that silently failed (private repo, network issue). Solution: bake handler into Docker image instead of runtime cloning. ## Debugging Worker Failures - Check RunPod dashboard logs for the endpoint - Exit code 2 = Python can't find the script file - Exit code 1 = Python runtime error in the handler - Look at `dockerArgs` — if it clones repos at runtime with `|| true`, failures are silent