#14963·kong

Admin API returns 500 instead of 400 for INVALID_FOREIGN_KEY / INVALID_WORKSPACE errors

Author: Adityaj0Created Aug 2, 2026Updated Aug 10, 2026

Is there an existing issue for this?

  • I have searched the existing issues

Kong version

Reproduced by code inspection against master @ 391ee48.

Current Behavior

kong/api/endpoints.lua maintains an ERRORS_HTTP_CODES table mapping kong.db.errors codes to Admin API HTTP status codes. Any error code missing from this table (or explicitly mapped to 500) falls through to:

lua
local status = ERRORS_HTTP_CODES[err_t.code]
if not status or status == 500 then
  return app_helpers.yield_error(err_t)
end

app_helpers.yield_error propagates to api_helpers.handle_error, which always responds with a generic 500 { message = "An unexpected error occurred" } and only logs the real error server-side, discarding the specific message from the client-facing response.

Two real, DAO-raised error codes are missing from ERRORS_HTTP_CODES:

  • Errors.codes.INVALID_FOREIGN_KEY — raised by validate_unique_row_method in kong/db/dao/init.lua whenever a unique lookup targets a foreign-typed field with a malformed value (reachable via the Admin API's generic :select_by_<field> lookups for any entity with a unique = true foreign-typed field, e.g. filter_chains, snis, upstreams).
  • Errors.codes.INVALID_WORKSPACE — raised by the postgres strategy (kong/db/strategies/postgres/init.lua) on a ws_id foreign-key-constraint violation, reachable when a workspace is deleted concurrently with a write to one of its entities.

Both produce safe, actionable, client-facing messages (e.g. "invalid foreign key: ..." / "invalid workspace '...'") that are currently hidden behind the generic 500, and both represent a 400-class, client-side problem — consistent with the already-mapped, analogous FOREIGN_KEY_VIOLATION and INVALID_PRIMARY_KEY codes (both 400).

Expected Behavior

Requests that trigger INVALID_FOREIGN_KEY or INVALID_WORKSPACE should receive a 400 response with the real error message, not a generic, opaque 500.

Steps To Reproduce

Code-path confirmation:

lua
local Errors = require "kong.db.errors"
print(Errors.codes.INVALID_FOREIGN_KEY)  -- 16
print(Errors.codes.INVALID_WORKSPACE)    -- 17

Neither appears as a key in ERRORS_HTTP_CODES in kong/api/endpoints.lua (lines 25-40 on master), while both are constructed and returned by the DAO layer (kong/db/dao/init.lua:365 and kong/db/strategies/postgres/init.lua:~290 respectively) and confirmed at the DAO level by spec/02-integration/03-db/02-db_core_entities_spec.lua for INVALID_WORKSPACE.

At a system level: perform an Admin API request that resolves to a unique lookup on a foreign-typed field with a value that fails the field's schema validation — the response is 500 with a generic body, instead of 400 with the real validation message.

Anything else?

I have a fix ready and will open a pull request referencing this issue.