oapi-codegen version: v2.7.2
Summary
When an OpenAPI schema has "type": "array" with a top-level "enum" key, oapi-codegen generates two simultaneous errors that make the output file fail to compile:
- A
const block is emitted for a slice type — Go does not permit const declarations for slice types.
- The string values in the
const block are written as bare unquoted identifiers instead of quoted string literals.
Both failures are always produced together from the same trigger and require the same fix.
Root cause
oapi-codegen's enum codegen path assumes the underlying Go type will always be a scalar (string, int, etc.). When enum appears on a schema whose Go representation is a slice ([]string), the generator enters that same path with a slice type and produces invalid Go.
The spec pattern that triggers this is:
{
"type": "array",
"items": { "type": "string" },
"enum": ["router", "general-purpose", "scan-host", "embedded"]
}
This is distinct from the standard pattern — enum on a type: string schema — which oapi-codegen handles correctly:
{
"type": "string",
"enum": ["router", "general-purpose", "scan-host", "embedded"]
}
Steps to reproduce
Create a minimal spec file bug.yaml:
openapi: "3.0.3"
info:
title: Bug Repro
version: "1.0"
paths: {}
components:
schemas:
SystemTypes:
type: array
items:
type: string
enum:
- router
- general-purpose
- scan-host
- embedded
Generate:
oapi-codegen --config=config.yaml --generate=types,skip-fmt bug.yaml
Generated output (v2.7.2)
// SystemTypes defines model for SystemTypes.
type SystemTypes = []string
// Defines values for SystemTypes.
const (
SystemTypesEmbedded SystemTypes = embedded // ❌ unquoted bare identifier
SystemTypesGeneralPurpose SystemTypes = general-purpose // ❌ unquoted + hyphen is subtraction operator
SystemTypesRouter SystemTypes = router // ❌ unquoted bare identifier
SystemTypesScanHost SystemTypes = scan-host // ❌ unquoted + hyphen is subtraction operator
)
Compiler errors
cannot declare const of type []string (non-comparable or non-constant type)
undefined: embedded
undefined: general
undefined: router
undefined: scan
Expected output
Since Go does not permit const declarations for slice types, compile-time enforcement is not achievable. The closest valid equivalent is a helper function:
// SystemTypes defines model for SystemTypes.
type SystemTypes = []string
// ValidSystemTypesElement reports whether s is a known element value for SystemTypes.
func ValidSystemTypesElement(s string) bool {
switch s {
case "router", "general-purpose", "scan-host", "embedded":
return true
default:
return false
}
}
Alternatively, the generator may skip enum codegen for array-typed schemas entirely and emit a warning, leaving validation to the caller. Either outcome is acceptable — the current behavior (uncompilable const block) is not.
Real-world spec source
Observed with the Tenable Vulnerability Management API (v2.7.2 generation). Example schema: Export_Assets_response-assets-chunk-v1.properties.system_types.
Verified that specs which use the standard pattern (enum inside items, or enum on a type: string schema) and they are working as expected
Note on spec conformance
The triggering pattern — enum at the array level rather than inside items — is technically non-standard per JSON Schema. The semantically correct form is to place enum inside items. However, this pattern appears in real-world vendor-provided specs that users have no control over.
The core invariant that must hold unconditionally is: a code generator must never silently produce Go code that does not compile. We consider any of the following acceptable resolutions:
- Detect that the resolved Go type is a slice, suppress
const generation, and optionally emit a comment listing the known values.
- Emit a warning identifying the schema as non-standard and skip enum codegen for it.
- Return a hard error pointing to the offending schema so the user can correct the spec.
Silently emitting a const block for a slice type requires manual patching before the generated file can be used.
oapi-codegen version: v2.7.2
Summary
When an OpenAPI schema has
"type": "array"with a top-level"enum"key,oapi-codegengenerates two simultaneous errors that make the output file fail to compile:constblock is emitted for a slice type — Go does not permitconstdeclarations for slice types.constblock are written as bare unquoted identifiers instead of quoted string literals.Both failures are always produced together from the same trigger and require the same fix.
Root cause
oapi-codegen's enum codegen path assumes the underlying Go type will always be a scalar (string,int, etc.). Whenenumappears on a schema whose Go representation is a slice ([]string), the generator enters that same path with a slice type and produces invalid Go.The spec pattern that triggers this is:
{ "type": "array", "items": { "type": "string" }, "enum": ["router", "general-purpose", "scan-host", "embedded"] }This is distinct from the standard pattern —
enumon atype: stringschema — whichoapi-codegenhandles correctly:{ "type": "string", "enum": ["router", "general-purpose", "scan-host", "embedded"] }Steps to reproduce
Create a minimal spec file
bug.yaml:Generate:
Generated output (v2.7.2)
Compiler errors
Expected output
Since Go does not permit
constdeclarations for slice types, compile-time enforcement is not achievable. The closest valid equivalent is a helper function:Alternatively, the generator may skip enum codegen for array-typed schemas entirely and emit a warning, leaving validation to the caller. Either outcome is acceptable — the current behavior (uncompilable
constblock) is not.Real-world spec source
Observed with the Tenable Vulnerability Management API (v2.7.2 generation). Example schema:
Export_Assets_response-assets-chunk-v1.properties.system_types.Verified that specs which use the standard pattern (
enuminsideitems, orenumon atype: stringschema) and they are working as expectedNote on spec conformance
The triggering pattern —
enumat the array level rather than insideitems— is technically non-standard per JSON Schema. The semantically correct form is to placeenuminsideitems. However, this pattern appears in real-world vendor-provided specs that users have no control over.The core invariant that must hold unconditionally is: a code generator must never silently produce Go code that does not compile. We consider any of the following acceptable resolutions:
constgeneration, and optionally emit a comment listing the known values.Silently emitting a
constblock for a slice type requires manual patching before the generated file can be used.