[Bug]: API key id exceeding 40 characters passes application validation but fails with an opaque 500 error due to VARCHAR(40) DB column limit
@Isuranga-2001 is already working on this.
Since Aug 17, 2026.
- Dominant language
- Go
- Stars
- 71
- Forks
- 111
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 110
Description
Please select the area the issue is related to
Platform API
Please select the aspect the issue is related to
Aspect/API (API backends, definitions, contracts, interfaces, OpenAPI)
Description
The API key id field has no length validation in the application layer — apiKeyNameMaxLength = 63 (internal/service/apikey.go:41) is only applied to server-generated names, never to a caller-supplied id. But the actual persisted column, api_keys.handle, is declared VARCHAR(40) in schema.postgres.sql/schema.sql/schema.sqlserver.sql. Any id longer than 40 characters therefore fails at the database layer on Postgres/SQL Server with value too long for type character varying(40), which the handler wraps into an opaque 500 INTERNAL_ERROR — the caller gets no indication the problem is field length.
This is invisible on SQLite (the default dev/CI database), since SQLite doesn't enforce declared VARCHAR(N) length at all — the identical request returns 201 Created there regardless of id length, which is why existing unit tests never catch it.
Steps to Reproduce
-
Start platform-api against a real Postgres backend:
docker compose -p platform-api-it -f it/docker-compose.postgres.yaml up -d --wait
docker exec -i platform-api-it-postgres-1 psql -U postgres -d platform_api_it < internal/database/schema.postgres.sql -
Create a config pointing [platform_api.database] at Postgres (driver = "postgres", host = "localhost", port = 55432, user = "postgres", password = "postgres", name = "platform_api_it", sslmode = "disable") and run:
export $(grep -v '^#' local-dev.env | xargs)
export APIP_CP_ENCRYPTION_KEY=$(cat resources/keys/encryption.key)
go run ./cmd/main.go -config <that-config> -
Log in and create a project + REST API:
TOKEN=$(curl -sk -X POST https://localhost:9243/api/portal/v0.9/auth/login \ --data-urlencode "username=admin" --data-urlencode "password=<admin-password>" \ | python3 -c "import json,sys;print(json.load(sys.stdin)['token'])")curl -sk -X POST https://localhost:9243/api/v0.9/projects -H "Authorization: Bearer $TOKEN" \ -d '{"handle":"repro-proj","displayName":"Repro Project"}'curl -sk -X POST https://localhost:9243/api/v0.9/rest-apis -H "Authorization: Bearer $TOKEN" \ -d '{"displayName":"Repro API","context":"/repro-api","version":"1.0.0","projectId":"repro-project","upstream":{"main":{"url":"https://example.com"}}}'
-
Create an API key with an id longer than 40 characters (e.g. 63): LONGID=$(python3 -c "print('a'*63)")
curl -sk -i -X POST https://localhost:9243/api/v0.9/rest-apis/repro-api/api-keys \ -H "Authorization: Bearer $TOKEN" \ -d "{\"id\":\"$LONGID\",\"displayName\":\"Long name key\",\"apiKey\":\"sk_example_1234567890abcdef\"}"
Actual result:
HTTP/2 500
{"status":"error","code":"INTERNAL_ERROR","message":"An unexpected error occurred.","trackingId":"39c2695d-b274-4c66-a150-df890d8fa020"}
with the real cause (value too long for type character varying(40)) only visible in the server log.
Expected result:
Either a clear 400 VALIDATION_FAILED response naming the actual length constraint, or the request should succeed if 63 characters is meant to be a valid id.
Control case (same request, SQLite instead of Postgres): returns 201 Created and silently persists the oversized value — proving the length is enforced inconsistently depending on which database backend is deployed.
Severity Level of the Issue
Severity/Major (Important functionality is broken. Should be prioritized. Doesn't need immediate attention)
Environment Details (with versions)
- PostgreSQL (repro): 16.15 (Debian, via postgres:16 Docker image)
- OS: macOS 26.6.1 (build 25G76), arm64
- Not reproducible on SQLite (schema.sqlite.sql), the default local/CI database
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.