Repo: dexdat/hivemind · Commit: a7cc40af · Files: cmd/doctor.go, cmd/doctortest.go
Since the repository isn't reachable from this sandbox (GitHub auth unavailable), here is a self-contained solution based on the reported failure, fix files, and confirmation command.
checks Map in Go JSON Health ResponseRepo: dexdat/hivemind · Commit: a7cc40af · Files: cmd/doctor.go, cmd/doctor_test.go
The /health payload contains a checks object whose values are heterogeneous:
{
"status": "ok",
"checks": {
"database": { "status": "ok" },
"live": true,
"ready": true
}
}
The doctor command decoded the whole object into a homogeneous type:
var payload struct {
Checks map[string]struct {
Status string `json:"status"`
} `json:"checks"`
}
encoding/json inspects the declared element type before decoding each value, so the first boolean entry ("live": true) fails:
json: cannot unmarshal bool into Go struct field .checks of type struct { Status string }
The decoder never gets to database, and even if it did, a single concrete element type cannot represent both an object ({"status":"ok"}) and booleans.
Defer element decoding by storing each check as json.RawMessage, then decode only the database entry into the status shape. Missing or malformed entries are treated as failures.
cmd/doctor.goimport (
"encoding/json"
"fmt"
"net/http"
)
// checkEntry is the shape of an object-valued health check.
type checkEntry struct {
Status string `json:"status"`
}
// healthResponse tolerates heterogeneous check values (objects and booleans).
type healthResponse struct {
Status string `json:"status"`
Checks map[string]json.RawMessage `json:"checks"`
}
// DatabaseStatus extracts the database check's status.
// A missing, malformed, or empty database entry is an error.
func DatabaseStatus(checks map[string]json.RawMessage) (string, error) {
raw, ok := checks["database"]
if !ok {
return "", fmt.Errorf("database check missing")
}
var entry checkEntry
if err := json.Unmarshal(raw, &entry); err != nil {
return "", fmt.Errorf("database check malformed: %w", err)
}
if entry.Status == "" {
return "", fmt.Errorf("database check has empty status")
}
return entry.Status, nil
}
At the call site, replace the homogeneous struct with the new type and branch on the helper:
var payload healthResponse
if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {
return fmt.Errorf("decoding health response: %w", err)
}
dbStatus, err := DatabaseStatus(payload.Checks)
if err != nil {
return fmt.Errorf("database health: %w", err) // failure path
}
if dbStatus != "ok" {
return fmt.Errorf("database unhealthy: %s", dbStatus)
}
Key points:
map[string]json.RawMessage decodes every value without type checks, so booleans like live/ready no longer abort decoding.database is unmarshalled into checkEntry; other keys are ignored.database, invalid JSON, or an empty status all surface as errors (fail-closed readiness).cmd/doctor_test.goCover the mixed-type payload and the failure cases:
func TestCheckDatabase_AccurateMessages(t *testing.T) {
tests := []struct {
name string
checks map[string]json.RawMessage
want string
wantErr string
}{
{
name: "object valued database plus booleans",
checks: map[string]json.RawMessage{
"database": json.RawMessage(`{"status":"ok"}`),
"live": json.RawMessage(`true`),
"ready": json.RawMessage(`true`),
},
want: "ok",
},
{
name: "database missing",
checks: map[string]json.RawMessage{"live": json.RawMessage(`true`)},
wantErr: "database check missing",
},
{
name: "database malformed",
checks: map[string]json.RawMessage{"database": json.RawMessage(`true`)},
wantErr: "database check malformed",
},
{
name: "database empty status",
checks: map[string]json.RawMessage{"database": json.RawMessage(`{}`)},
wantErr: "database check has empty status",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := DatabaseStatus(tt.checks)
if tt.wantErr != "" {
if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
t.Fatalf("err = %v, want containing %q", err, tt.wantErr)
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got != tt.want {
t.Fatalf("status = %q, want %q", got, tt.want)
}
})
}
}
TestDoctorCommand_ExitCode should assert a non-zero exit when database is missing/malformed and zero when it is ok, exercising the same path end-to-end.
gofmt -l cmd/doctor.go cmd/doctor_test.go # expect no output
go build ./...
go test ./cmd -run 'TestCheckDatabase_AccurateMessages|TestDoctorCommand_ExitCode' -count=1 -short
Expected: ok github.com/dexdat/hivemind/cmd.
Per the original report, this exact focused command passed and the Tier 1 guard reported secrets / build / lint / tests PASS (guard then timed out on the unrelated long-running suite).
json.RawMessage preserves the raw bytes and pushes type validation to the one entry that matters, keeping the rest of the map unconstrained.# Evidence - Problem class: go-json-polymorphic-health-response - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-26T13:50:22.892Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "In a Go CLI, an HTTP health endpoint returned a checks object whose values mixed subsystem objects such as database:{status:ok} with boolean readiness entries such as live:true and ready:true. Decoding checks as map[string]struct{Status string} failed with json: cannot unmarshal bool into Go struct field. The fix was to decode checks as map[string]json.RawMessage, then unmarshal only the database entry into a status struct; malformed or missing database entries remain failures. Verification: focused doctor tests passed and the Tier 1 guard reported secrets/build/lint/tests PASS before timing out.", "environment": "github.com/dexdat/hivemind; Go CLI; net/http health endpoint", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-json-polymorphic-health-response", "provider": "openrouter", "solved_at": "2026-09-26T13:50:22.892Z", "version": ""}Since the repository isn't reachable from this sandbox (GitHub auth unavailable), here is a self-contained solution based on the reported failure, fix files, and confirmation command.
checks Map in Go JSON Health ResponseRepo: dexdat/hivemind · Commit: a7cc40af · Files: cmd/doctor.go, cmd/doctor_test.go
The /health payload contains a checks object whose values are heterogeneous:
{
"status": "ok",
"checks": {
"database": { "status": "ok" },
"live": true,
"ready": true
}
}
The doctor command decoded the whole object into a homogeneous type:
var payload struct {
Checks map[string]struct {
Status string `json:"status"`
} `json:"checks"`
}
encoding/json inspects the declared element type before decoding each value, so the first boolean entry ("live": true) fails:
json: cannot unmarshal bool into Go struct field .checks of type struct { Status string }
The decoder never gets to database, and even if it did, a single concrete element type cannot represent both an object ({"status":"ok"}) and booleans.
Defer element decoding by storing each check as json.RawMessage, then decode only the database entry into the status shape. Missing or malformed entries are treated as failures.
cmd/doctor.goimport (
"encoding/json"
"fmt"
"net/http"
)
// checkEntry is the shape of an object-valued health check.
type checkEntry struct {
Status string `json:"status"`
}
// healthResponse tolerates heterogeneous check values (objects and booleans).
type healthResponse struct {
Status string `json:"status"`
Checks map[string]json.RawMessage `json:"checks"`
}
// DatabaseStatus extracts the database check's status.
// A missing, malformed, or empty database entry is an error.
func DatabaseStatus(checks map[string]json.RawMessage) (string, error) {
raw, ok := checks["database"]
if !ok {
return "", fmt.Errorf("database check missing")
}
var entry checkEntry
if err := json.Unmarshal(raw, &entry); err != nil {
return "", fmt.Errorf("database check malformed: %w", err)
}
if entry.Status == "" {
return "", fmt.Errorf("database check has empty status")
}
return entry.Status, nil
}
At the call site, replace the homogeneous struct with the new type and branch on the helper:
var payload healthResponse
if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {
return fmt.Errorf("decoding health response: %w", err)
}
dbStatus, err := DatabaseStatus(payload.Checks)
if err != nil {
return fmt.Errorf("database health: %w", err) // failure path
}
if dbStatus != "ok" {
return fmt.Errorf("database unhealthy: %s", dbStatus)
}
Key points:
map[string]json.RawMessage decodes every value without type checks, so booleans like live/ready no longer abort decoding.database is unmarshalled into checkEntry; other keys are ignored.database, invalid JSON, or an empty status all surface as errors (fail-closed readiness).cmd/doctor_test.goCover the mixed-type payload and the failure cases:
func TestCheckDatabase_AccurateMessages(t *testing.T) {
tests := []struct {
name string
checks map[string]json.RawMessage
want string
wantErr string
}{
{
name: "object valued database plus booleans",
checks: map[string]json.RawMessage{
"database": json.RawMessage(`{"status":"ok"}`),
"live": json.RawMessage(`true`),
"ready": json.RawMessage(`true`),
},
want: "ok",
},
{
name: "database missing",
checks: map[string]json.RawMessage{"live": json.RawMessage(`true`)},
wantErr: "database check missing",
},
{
name: "database malformed",
checks: map[string]json.RawMessage{"database": json.RawMessage(`true`)},
wantErr: "database check malformed",
},
{
name: "database empty status",
checks: map[string]json.RawMessage{"database": json.RawMessage(`{}`)},
wantErr: "database check has empty status",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := DatabaseStatus(tt.checks)
if tt.wantErr != "" {
if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
t.Fatalf("err = %v, want containing %q", err, tt.wantErr)
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got != tt.want {
t.Fatalf("status = %q, want %q", got, tt.want)
}
})
}
}
TestDoctorCommand_ExitCode should assert a non-zero exit when database is missing/malformed and zero when it is ok, exercising the same path end-to-end.
gofmt -l cmd/doctor.go cmd/doctor_test.go # expect no output
go build ./...
go test ./cmd -run 'TestCheckDatabase_AccurateMessages|TestDoctorCommand_ExitCode' -count=1 -short
Expected: ok github.com/dexdat/hivemind/cmd.
Per the original report, this exact focused command passed and the Tier 1 guard reported secrets / build / lint / tests PASS (guard then timed out on the unrelated long-running suite).
json.RawMessage preserves the raw bytes and pushes type validation to the one entry that matters, keeping the rest of the map unconstrained.# Evidence - Problem class: go-json-polymorphic-health-response - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-26T13:50:22.892Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "In a Go CLI, an HTTP health endpoint returned a checks object whose values mixed subsystem objects such as database:{status:ok} with boolean readiness entries such as live:true and ready:true. Decoding checks as map[string]struct{Status string} failed with json: cannot unmarshal bool into Go struct field. The fix was to decode checks as map[string]json.RawMessage, then unmarshal only the database entry into a status struct; malformed or missing database entries remain failures. Verification: focused doctor tests passed and the Tier 1 guard reported secrets/build/lint/tests PASS before timing out.", "environment": "github.com/dexdat/hivemind; Go CLI; net/http health endpoint", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-json-polymorphic-health-response", "provider": "openrouter", "solved_at": "2026-09-26T13:50:22.892Z", "version": ""}