Skip to content

fix(server): encode typed slices/maps in resource status/spec over the wire#119

Merged
astrojerms merged 1 commit into
mainfrom
fix/normalize-typed-slices
Jul 11, 2026
Merged

fix(server): encode typed slices/maps in resource status/spec over the wire#119
astrojerms merged 1 commit into
mainfrom
fix/normalize-typed-slices

Conversation

@astrojerms

Copy link
Copy Markdown
Owner

Symptom

Browsing a ProxmoxNode in the UI returned:

HTTP 500: {"code":13,"message":"encode: status: proto: invalid type: []string"}

Cause

ProxmoxNode's single-node Get enriches status.storages / status.bridges as []string (internal consumers and the dependent-dropdown resolution expect that concrete type). When the server encodes status into a google.protobuf.Struct, normalizeValue (resource.go) only recursed into []any — a typed slice like []string fell through default unchanged, and structpb.NewStruct rejects it with invalid type: []string. Every resource-encode path (GET, list, watch) routes through this, so the node was unviewable.

Fix

Harden the wire-normalization boundary rather than the source (keeping the internal []string contract that tests + dropdown resolution rely on). normalizeValue's fallback now uses reflection to convert any typed slice/array/map to the generic []any / map[string]any that structpb accepts, recursing through elements. []byte still passes through (structpb encodes it as base64). This fixes the class of bug for any provider's status/spec, including external plugins — not just this one field.

Test

TestResourceToProtoEncodesTypedContainers drives the real resourceToProto path with []string (the exact trigger), []int, map[string]string, a typed slice nested inside []any, and []byte, asserting correct structpb values.

Local CI

gofmt / go vet / staticcheck / golangci-lint / modernize (generated-filtered) / go test (server + proxmox) / go test -race (server) all green.

Note: the encode bug is server-side and fully covered by the unit test; end-to-end reproduction against live Proxmox is currently gated by an unrelated macOS Local Network Privacy block on the dev machine.

…e wire

Browsing a ProxmoxNode 500'd with
`encode: status: proto: invalid type: []string`. The node Get enriches
status with storages/bridges as []string (internal consumers + the
dependent-dropdown resolution expect that type), but normalizeValue —
which prepares spec/status for structpb.NewStruct — only recursed into
[]any, so a typed slice fell through unchanged and structpb rejected it.

Fix normalizeValue at the wire boundary (not the source, to preserve the
internal []string contract): a reflection fallback converts any typed
slice/array/map to the generic []any / map[string]any structpb accepts,
recursing through elements. []byte still passes through (structpb encodes
it as base64). This hardens every provider's status/spec — including
external plugins — not just this one field.

Added TestResourceToProtoEncodesTypedContainers covering []string, []int,
map[string]string, a typed slice nested in []any, and []byte.
@astrojerms astrojerms merged commit 6a79f51 into main Jul 11, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant