{"record":{"id":"dd1bb92e78cc044d","repo":"multica-ai/multica","slug":"successful-runtime-probes-require-all-counts","errorCode":null,"errorMessage":"successful runtime probes require all counts","messagePattern":"successful runtime probes require all counts","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"server/internal/handler/client_usage.go","lineNumber":200,"sourceCode":"\t\treturn \"unknown\"\n\t}\n}\n\nfunc validateClientUsageRuntime(probe clientUsageRuntimeProbe) (validatedRuntimeProbe, error) {\n\tresult := strings.ToLower(strings.TrimSpace(probe.ProbeResult))\n\tif result != \"success\" && result != \"error\" {\n\t\treturn validatedRuntimeProbe{}, errors.New(\"runtime probe_result must be success or error\")\n\t}\n\tvalidated := validatedRuntimeProbe{Result: pgtype.Text{String: result, Valid: true}}\n\tif result == \"error\" {\n\t\tif probe.RuntimeCount != nil || probe.ProviderSummary != nil || probe.OnlineCount != nil || probe.OfflineCount != nil {\n\t\t\treturn validatedRuntimeProbe{}, errors.New(\"failed runtime probes must not include counts\")\n\t\t}\n\t\treturn validated, nil\n\t}\n\n\tif probe.RuntimeCount == nil || probe.ProviderSummary == nil || probe.OnlineCount == nil || probe.OfflineCount == nil {\n\t\treturn validatedRuntimeProbe{}, errors.New(\"successful runtime probes require all counts\")\n\t}\n\tif *probe.RuntimeCount < 0 || *probe.RuntimeCount > 1000 || *probe.OnlineCount < 0 || *probe.OfflineCount < 0 || *probe.OnlineCount+*probe.OfflineCount != *probe.RuntimeCount {\n\t\treturn validatedRuntimeProbe{}, errors.New(\"invalid runtime counts\")\n\t}\n\tif len(probe.ProviderSummary) > 32 {\n\t\treturn validatedRuntimeProbe{}, errors.New(\"too many runtime providers\")\n\t}\n\tvar providerTotal int64\n\tfor provider, count := range probe.ProviderSummary {\n\t\tif !providerNamePattern.MatchString(provider) || count < 0 || count > 1000 {\n\t\t\treturn validatedRuntimeProbe{}, errors.New(\"invalid runtime provider summary\")\n\t\t}\n\t\tproviderTotal += int64(count)\n\t}\n\tif providerTotal != int64(*probe.RuntimeCount) {\n\t\treturn validatedRuntimeProbe{}, errors.New(\"runtime provider counts do not match runtime_count\")\n\t}\n\tsummary, err := json.Marshal(probe.ProviderSummary)","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/handler/client_usage.go#L182-L218","documentation":"The inverse rule from error 45: when probe_result is 'success', all four fields — runtime_count, provider_summary, online_count, offline_count — must be present (non-nil). A successful probe is expected to report its full count vector; the server will not default missing ones to zero because a silently missing count would be indistinguishable from an unreported probe. Pointer-nil checks mean explicit JSON nulls also fail here.","triggerScenarios":"POST a success probe missing any key, e.g. {\"probe_result\":\"success\",\"runtime_count\":10,\"online_count\":4,\"offline_count\":6} with no provider_summary, or with \"online_count\":null. All four must appear with concrete values.","commonSituations":"Client omitting provider_summary when the provider map is empty instead of sending {}; omitempty tags dropping zero-valued counts; partial refactor where a renamed field stopped serializing; nulls emitted for uncollected metrics.","solutions":["On the success path always set all four fields; use {} for an empty provider_summary, 0 for zero counts.","Remove omitempty from these four fields in the client payload struct, or branch to a success-specific struct.","Never send JSON null for any of the four on success.","Round-trip test: marshal a success probe and assert all four keys exist in the JSON."],"exampleFix":"// before\ntype probePayload struct {\n    Result        string           `json:\"probe_result\"`\n    RuntimeCount  *int32           `json:\"runtime_count,omitempty\"`\n    OnlineCount   *int32           `json:\"online_count,omitempty\"`\n    OfflineCount  *int32           `json:\"offline_count,omitempty\"`\n    Summary       map[string]int32 `json:\"provider_summary,omitempty\"`\n}\n\n// after\ntype probePayload struct {\n    Result        string           `json:\"probe_result\"`\n    RuntimeCount  *int32           `json:\"runtime_count\"`\n    OnlineCount   *int32           `json:\"online_count\"`\n    OfflineCount  *int32           `json:\"offline_count\"`\n    Summary       map[string]int32 `json:\"provider_summary\"`\n}","handlingStrategy":"type-guard","validationCode":"const hasAllCounts = (p) =>\n  Number.isInteger(p.runtime_count) && Number.isInteger(p.online_count) &&\n  Number.isInteger(p.offline_count) && p.provider_summary !== null && p.provider_summary !== undefined;\n\nfunction assertSuccessProbe(p) {\n  if (normalizeProbeResult(p.probe_result) !== 'success') return;\n  if (!hasAllCounts(p)) throw new TypeError('success probes require runtime_count, online_count, offline_count, and provider_summary ({} for empty)');\n}","typeGuard":"const isSuccessProbeComplete = (p) => p.probe_result?.toLowerCase() === 'success' && ['runtime_count','online_count','offline_count'].every(k => Number.isInteger(p[k])) && typeof p.provider_summary === 'object' && p.provider_summary !== null;","tryCatchPattern":null,"preventionTips":["Use a success-specific payload struct without omitempty on the four required fields.","Send {} for an empty provider map — never omit it on success.","Snapshot-test the serialized success payload asserting all four keys are present."],"tags":["validation","telemetry","contract","http-400"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}