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

  1. Verify the GID is still valid (list downloads and match) before operating on it
  2. If the aria2 daemon restarted, re-add the download rather than polling the stale GID
  3. 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

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.