What happened
POST /api/v2/files accepts and stores a gzipped tar without error, returning a valid hash. Any later use of that file — e.g. POST /api/v2/organizations/{org}/templateversions — panics:
{
"message": "Unable to parse workspace tags",
"detail": "Panic occurred in preview. This should not happen, please report this to Coder.; panic in preview: runtime error: invalid memory address or nil pointer dereference"
}
The message points at workspace tag parsing, which is misleading — the tag step appears to be simply the first consumer of the filesystem. The actual cause is the archive, uploaded several steps earlier.
Reproduction
mkdir t && printf 'terraform { required_providers { coder = { source = "coder/coder" } } }\n' > t/main.tf
# gzipped — the mistake
tar czf t.tar.gz -C t .
FID=$(curl -s -X POST -H "Coder-Session-Token: $TOKEN" \
-H "Content-Type: application/x-tar" --data-binary @t.tar.gz \
"$CODER_URL/api/v2/files" | jq -r .hash)
# succeeds and returns a hash
curl -s -X POST -H "Coder-Session-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"storage_method\":\"file\",\"file_id\":\"$FID\",\"provisioner\":\"terraform\",\"message\":\"x\"}" \
"$CODER_URL/api/v2/organizations/$ORG/templateversions"
# panics
An empty template panics too — the template content is never reached.
Replacing tar czf with tar cf fixes it completely.
Why it's confusing in practice
- The upload succeeds and returns a hash, so the archive looks accepted.
- The error names workspace tags, which has nothing to do with the cause.
- It reproduces on an empty template, which rules out the template and sends you looking at permissions, tokens, and Terraform instead.
coder templates push works on the same server with the same template, so the CLI and the API disagree in a way I could not find documented.
I spent a while ruling out permissions (an owner token fails identically to a template-admin service account) and template content before finding it.
Suggested fixes
I have not read the source directly, so treat the pointers below as a starting point rather than a diagnosis:
- Reject unparseable archives at upload. The handler for
/api/v2/files appears to validate only the Content-Type header without reading the archive. Validating there would turn this into a clean 400 at the point of the mistake, rather than a panic much later.
- Guard the tar reader. The panic looks like a nil filesystem being returned when the tar cannot be read, then dereferenced by its first caller.
- Optionally accept gzip, or document that only
application/x-tar and application/zip are supported — the asymmetry with the CLI is the part that cost me the most time.
Environment
- Coder
v2.36.1+9548f23 (ghcr.io/coder/coder:latest)
- Docker Compose, Postgres 18
terraform-provider-coder v2.18.0
- Reproduced on
:latest as of 2026-09-02
What happened
POST /api/v2/filesaccepts and stores a gzipped tar without error, returning a valid hash. Any later use of that file — e.g.POST /api/v2/organizations/{org}/templateversions— panics:{ "message": "Unable to parse workspace tags", "detail": "Panic occurred in preview. This should not happen, please report this to Coder.; panic in preview: runtime error: invalid memory address or nil pointer dereference" }The message points at workspace tag parsing, which is misleading — the tag step appears to be simply the first consumer of the filesystem. The actual cause is the archive, uploaded several steps earlier.
Reproduction
An empty template panics too — the template content is never reached.
Replacing
tar czfwithtar cffixes it completely.Why it's confusing in practice
coder templates pushworks on the same server with the same template, so the CLI and the API disagree in a way I could not find documented.I spent a while ruling out permissions (an owner token fails identically to a template-admin service account) and template content before finding it.
Suggested fixes
I have not read the source directly, so treat the pointers below as a starting point rather than a diagnosis:
/api/v2/filesappears to validate only theContent-Typeheader without reading the archive. Validating there would turn this into a clean 400 at the point of the mistake, rather than a panic much later.application/x-tarandapplication/zipare supported — the asymmetry with the CLI is the part that cost me the most time.Environment
v2.36.1+9548f23(ghcr.io/coder/coder:latest)terraform-provider-coderv2.18.0:latestas of 2026-09-02