AlistGo/alist · error · ErrNullResult
result is null
Error message
result is null
What it means
ErrNullResult is returned by clientResponse.decode when a JSON-RPC response carries no error but its result field is null/absent. The client treats a null result as protocol failure rather than a legitimate empty value, because every aria2 method it wraps is expected to return something (a gid, a struct, an array).
Source
Thrown at pkg/aria2/rpc/json2.go:100
var c clientResponse
if err := json.NewDecoder(r).Decode(&c); err != nil {
return err
}
return c.decode(reply)
}
type ErrorCode int
const (
E_PARSE ErrorCode = -32700
E_INVALID_REQ ErrorCode = -32600
E_NO_METHOD ErrorCode = -32601
E_BAD_PARAMS ErrorCode = -32602
E_INTERNAL ErrorCode = -32603
E_SERVER ErrorCode = -32000
)
var ErrNullResult = errors.New("result is null")
type Error struct {
// A Number that indicates the error type that occurred.
Code ErrorCode `json:"code"` /* required */
// A String providing a short description of the error.
// The message SHOULD be limited to a concise single sentence.
Message string `json:"message"` /* required */
// A Primitive or Structured value that contains additional information about the error.
Data interface{} `json:"data"` /* optional */
}
func (e *Error) Error() string {
return e.Message
}
View on GitHub (pinned to 843d9dc814)
Solutions
- Verify the GID is still valid (list downloads and match) before operating on it
- If the aria2 daemon restarted, re-add the download rather than polling the stale GID
- If the endpoint is a non-aria2 JSON-RPC server, wrap calls to tolerate null results or switch to a real aria2 daemon
Example fix
// before
st, err := c.TellStatus(gid)
// after: tolerate tasks lost after a daemon restart
st, err := c.TellStatus(gid)
if err == rpc.ErrNullResult {
// gid no longer known to aria2; re-add or drop the task
gid, err = c.AddURI([]string{url}, opts)
} Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
func isNullResult(err error) bool {
return errors.Is(err, rpc.ErrNullResult)
} Try / catch
st, err := c.TellStatus(gid)
if err != nil {
if errors.Is(err, rpc.ErrNullResult) {
// gid unknown to daemon (expired/restarted): re-add or drop
gid, err = c.AddURI([]string{taskUrl}, nil)
}
// handle other errors
} Prevention
- Detect aria2 daemon restarts (connection drops) and invalidate cached GIDs
- Compare GIDs against the live download list after daemon restarts
- Use errors.Is with the exported rpc.ErrNullResult sentinel rather than string matching
When it happens
Trigger: Any rpc.Client call whose daemon reply has "result": null — commonly an expired or invalid GID passed to TellStatus/ChangeOption, or a non-conforming aria2-compatible daemon (AriaNg-adjacent wrappers, some forks) returning null for empty lists.
Common situations: Polling a download status after aria2 restarted and lost its task table (GIDs no longer valid); using a third-party JSON-RPC endpoint that returns null instead of [] or ""; version drift where a method's reply shape changed.
Related errors
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/412cc5d8e0235d5e.
Report an issue: GitHub.