fix(apiserver): stop job-control panic on int/int64 type mismatch
xcecli jobs kill/stop/resume/checkpoint failed for every job with an empty error body. models.JobInfo.JobStatus/.ArrayIdx are plain Go `int`, but validateJobControl/foundJob asserted them as `int64` via a bare type assertion, which always panicked; Gin's Recovery() middleware swallowed the panic and returned an empty 500. Fixes gitea#45 / bug-1742. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y4M5MJM2zK6nU43da267Ku
This commit is contained in:
parent
83d40fbb33
commit
343639fc7e
3 changed files with 128 additions and 10 deletions
|
|
@ -20164,6 +20164,32 @@
|
|||
],
|
||||
"occurrences": 1,
|
||||
"last_seen": "2026-08-30T22:15:00Z"
|
||||
},
|
||||
{
|
||||
"id": "bug-1742",
|
||||
"timestamp": "2026-09-01T04:10:00Z",
|
||||
"gitea_issue": 45,
|
||||
"error_message": "Gitea issue #45: `xcecli jobs kill <jobid>` fails for every job-control action (kill/stop/resume/checkpoint) with `request to /xce/v1/jobs/<id>/control failed: []` -- an empty error body, not a normal ReturnError JSON payload. Reproduced by static analysis of the full CLI->apiserver call path (job ID conversion verified correct by hand: MakeJobID(1,0,1788186846,0,1) == 73932643848159233, matching the URL in the report, so the numeric-vs-string ID mismatch in the bug report is a red herring).",
|
||||
"file": "src/frontend/apiserver/controllers/jobs.go (validateJobControl:2997-3072, foundJob:3077-3089, ControlJobByID:2515-2599), src/frontend/apiserver/models/jobs.go (JobInfo.JobStatus/.ArrayIdx:489,493), src/frontend/apiserver/store/convert.go (StructToOrderMap:10-35), src/frontend/apiserver/router/routers.go (gin.Default() Recovery middleware:19), src/frontend/xcecli (request.go:219 HandleErrorResponse empty-body fallback)",
|
||||
"root_cause": "models.JobInfo declares JobStatus and ArrayIdx as plain Go `int` (jobs.go:489,493), not `int64`. store.StructToOrderMap builds jobinfo.Data via reflection (val.Field(i).Interface()), which preserves the field's concrete runtime type -- so Data[\"job_status\"] and Data[\"array_idx\"] are boxed as `int`, never `int64`. validateJobControl's guard at jobs.go:3014 (`if jobStatus, ok := rawStatus.(int64); ok`) therefore ALWAYS evaluates false for every job, unconditionally routing into the `else` error branch (3052-3060). That branch immediately does an UNCHECKED single-return assertion at jobs.go:3057, `int(jobinfo.Data[\"array_idx\"].(int64))` -- since array_idx is actually `int`, this panics with `interface conversion: interface {} is int, not int64` on every single job-control call, regardless of job status, action, or whether the job is an array member (the reporter's job happening to be an array index is incidental; the same unsafe `.(int64)` pattern is repeated at jobs.go:3024/3031/3040/3048/3066, and in foundJob at 3081-3082 for the array-index-lookup path). Gin's default Recovery() middleware (routers.go:19) catches the panic and returns an empty 500 body with no JSON, which is exactly what the xcecli client's error-fallback path (request.go:219, `HandleErrorResponse`) renders as `\"%s failed: [%s]\"` with an empty httpResp.String() -- producing the reported `failed: []` message. Confirmed the type mismatch directly by reading the struct declarations; confirmed the panic site's code by reading validateJobControl in full; not yet confirmed via a live repro/server-log stack trace (static analysis only this session).",
|
||||
"fix": "FIXED (2026-09-01). validateJobControl (jobs.go:2997) now converts job_status and array_idx via utils.IntOrInt64() (already used elsewhere for this exact int/int64 mismatch, e.g. processJobData) instead of bare `.(int64)` assertions -- a failed conversion is now reported as a normal failedJobs entry with a descriptive msg instead of panicking. foundJob (jobs.go:3077) gets the same fix for its array-index lookup path. TDD: added TestValidateJobControl_HandlesRealJobInfoTypes (builds a real models.JobInfo and converts it via store.StructToOrderMap(), the same reflection path production uses, then asserts validateJobControl doesn't panic and returns a correctly-typed success job -- this is the test that would have caught the original bug, since it exercises the real int/int64 boundary instead of hand-built int64 map literals), TestValidateJobControl_RejectsNonKillableStatus, and TestFoundJob_MatchesRealArrayIdxType (jobs_test.go). Confirmed red (panic at jobs.go:3057, \"interface conversion: interface {} is int, not int64\") before the fix, green after. Full apiserver suite (store/utils/controllers/backend/backend/auth) passes with zero regressions.",
|
||||
"tags": [
|
||||
"apiserver",
|
||||
"panic",
|
||||
"type-assertion",
|
||||
"interface-conversion",
|
||||
"job-control",
|
||||
"kill",
|
||||
"xcecli",
|
||||
"recovery-middleware",
|
||||
"empty-error-body",
|
||||
"new",
|
||||
"found-static-analysis",
|
||||
"needs-live-repro",
|
||||
"fixed"
|
||||
],
|
||||
"occurrences": 1,
|
||||
"last_seen": "2026-09-01T04:40:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue