Skip to content

Dynamic group Architecture filter for x64/x86 never matches (stored value is amd64, not x64) #3166

Description

@ToddHebebrand

Reported by semotech in #bugs (Discord, message 1534625902045167667).

Report (PII-redacted):

Reporting a small UI bug in Operations / Device Groups - Setting up a Dynamic Group Type for Intel Macs. Created condition for "Architecture" to match "X64" and even pressed "Refresh" but count just shows 0! Same with "X86" even tho there are machines enrolled that match all 3 criteria. Only option that does work and shows a machines list is "Arm64"!

Filed automatically by @breeze-discord triage. Verify and add labels/repro as needed.

Triage analysis

The reported behavior is real: dynamic-group filtering on the Architecture field is broken for x64/x86 because of a naming mismatch between what agents report and what the dynamic-group enum expects. The Go agent reports runtime.GOARCH verbatim as the device's architecture (agent/internal/collectors/hardware.go:37-48), which yields amd64 on Intel/x64 machines and arm64 on Apple Silicon/ARM machines — Go never emits x64 or x86. The enrollment handler stores that raw value into devices.architecture with no translation (apps/api/src/routes/agents/enrollment.ts:646, 689). Meanwhile the dynamic-group filter field definition advertises enum values x64, x86, arm64 (apps/api/src/services/filterEngine.ts:90) and the filter engine resolves the architecture field straight to the raw devices.architecture column with no value mapping (filterEngine.ts:160-170, getColumnForField). So a condition like architecture equals x64 is compared against a column literally containing amd64 and never matches (0 devices), while architecture equals arm64 happens to match by coincidence because Go's arm64 spelling is identical to the enum's. There is an existing helper, normalizeAgentArchitecture (apps/api/src/routes/agents/helpers.ts:187-197), that maps amd64/x86_64/x64amd64 and arm64/aarch64arm64, but it's only used for agent-binary version matching in heartbeat.ts, not applied when writing/filtering the device's own architecture field. Windows agents likely have the same issue for 32-bit (386 vs enum x86).

Affected code

  • agent/internal/collectors/hardware.go:32-48 — Agent reports raw runtime.GOARCH (amd64/arm64) as architecture; never emits 'x64' or 'x86'.
  • apps/api/src/routes/agents/enrollment.ts:634-703 — data.architecture is stored verbatim into devices.architecture on enroll/re-enroll with no normalization to the UI enum values.
  • apps/api/src/services/filterEngine.ts:90 — Dynamic-group field definition declares enum values x64/x86/arm64, which don't match the stored raw GOARCH strings.
  • apps/api/src/services/filterEngine.ts:160-170 — getColumnForField maps 'architecture' straight to the devices.architecture column with no value translation before comparison.
  • apps/api/src/routes/agents/helpers.ts:187-197 — normalizeAgentArchitecture already maps amd64/x86_64/x64 -> amd64 and arm64/aarch64 -> arm64, but is only used for agent-binary pinning, not applied to the device's stored architecture or in the filter engine.

Potential fix

Normalize architecture to the documented enum (x64/x86/arm64, or pick one canonical convention and update docs) either when persisting devices.architecture at enrollment/heartbeat time, or in filterEngine's getColumnForField/applyOperator for the 'architecture' field by mapping amd64<->x64 and 386<->x86 before comparing.

Triage analysis, affected code, and fix sketch above were produced by automated investigation (@breeze-discord). Verify before relying on them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions