fix: NULL-scan bug in LXC target resolution for entities without a host attribute
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled

Found live: `run` against lxc:caddy failed with "missing pve_id" even though
pve_id=121 was present — caddy is an inventory-seeded LXC with no `host`
attribute at all (only pct_create-provisioned LXCs set one). The combined
query scanned attributes->>'host' (SQL NULL) into a plain Go string, which
errors the whole Scan — including the pve_id column that scanned fine.
COALESCE the host column to '' so a missing host attribute degrades to the
documented default instead of failing the whole resolution.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 09:32:45 +02:00
parent d52968876a
commit 9539759db6
2 changed files with 12 additions and 2 deletions

View File

@@ -163,7 +163,12 @@ func resolveRunTarget(ctx context.Context, pool *db.Pool, targetSlug string) (ho
} }
if strings.HasPrefix(targetSlug, "lxc:") { if strings.HasPrefix(targetSlug, "lxc:") {
var pveID, hostAttr string var pveID, hostAttr string
if qerr := pool.QueryRow(ctx, "SELECT attributes->>'pve_id', attributes->>'host' FROM entities WHERE slug = $1", targetSlug).Scan(&pveID, &hostAttr); qerr != nil || pveID == "" { // COALESCE the host column: many older LXC entities (seeded from
// inventory, not provisioned by pct_create) have pve_id but no host
// attribute at all. Scanning a SQL NULL into a plain string errors
// the whole row, wrongly reporting "missing pve_id" even when it was
// present — COALESCE avoids the NULL, "" is handled below.
if qerr := pool.QueryRow(ctx, "SELECT attributes->>'pve_id', COALESCE(attributes->>'host', '') FROM entities WHERE slug = $1", targetSlug).Scan(&pveID, &hostAttr); qerr != nil || pveID == "" {
return "", "", nil, fmt.Errorf("LXC not found or missing pve_id: %s", targetSlug) return "", "", nil, fmt.Errorf("LXC not found or missing pve_id: %s", targetSlug)
} }
hostSlug := hostAttr hostSlug := hostAttr

View File

@@ -1196,7 +1196,12 @@ func resolveExecTarget(ctx context.Context, pool *db.Pool, targetSlug string) (h
} }
if strings.HasPrefix(targetSlug, "lxc:") { if strings.HasPrefix(targetSlug, "lxc:") {
var pveID, hostAttr string var pveID, hostAttr string
if qerr := pool.QueryRow(ctx, "SELECT attributes->>'pve_id', attributes->>'host' FROM entities WHERE slug = $1", targetSlug).Scan(&pveID, &hostAttr); qerr != nil || pveID == "" { // COALESCE the host column: many older LXC entities (seeded from
// inventory, not provisioned by pct_create) have pve_id but no host
// attribute at all. Scanning a SQL NULL into a plain string errors
// the whole row, wrongly reporting "missing pve_id" even when it was
// present — COALESCE avoids the NULL, "" is handled below.
if qerr := pool.QueryRow(ctx, "SELECT attributes->>'pve_id', COALESCE(attributes->>'host', '') FROM entities WHERE slug = $1", targetSlug).Scan(&pveID, &hostAttr); qerr != nil || pveID == "" {
return "", "", nil, fmt.Errorf("LXC not found or missing pve_id: %s", targetSlug) return "", "", nil, fmt.Errorf("LXC not found or missing pve_id: %s", targetSlug)
} }
hostSlug := hostAttr hostSlug := hostAttr