AlistGo/alist · error

decode darkibox result failed: %w

Error message

decode darkibox result failed: %w

What it means

The API call fully succeeded (HTTP 200, provider status 200, non-empty Result) but json.Unmarshal of resp.Result into the caller's target struct failed. The response JSON shape does not match the Go struct being decoded into — schema drift or an unexpected payload type.

Source

Thrown at drivers/darkibox/util.go:48

	r, err := base.RestyClient.R().
		SetContext(ctx).
		SetQueryParams(query).
		SetResult(&resp).
		Get(apiBase + endpoint)
	if err != nil {
		return err
	}
	if r.StatusCode() != http.StatusOK {
		return fmt.Errorf("darkibox http error: %d", r.StatusCode())
	}
	if resp.Status != 200 {
		return fmt.Errorf("darkibox api error: status=%d msg=%s", resp.Status, resp.Msg)
	}
	if out == nil || len(resp.Result) == 0 || string(resp.Result) == "null" {
		return nil
	}
	if err := json.Unmarshal(resp.Result, out); err != nil {
		return fmt.Errorf("decode darkibox result failed: %w", err)
	}
	return nil
}

// fldIDStr converts a folder ID (which may be the root "0") to a string suitable for API params.
func fldIDStr(id string) string {
	if id == "" {
		return "0"
	}
	return id
}

// encodeFolderID prefixes a folder ID so we can distinguish folders from files.
func encodeFolderID(id int64) string {
	return "d:" + strconv.FormatInt(id, 10)
}

// encodeFileID prefixes a file code so we can distinguish files from folders.

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Log resp.Result (raw JSON) at debug level and compare it against the target struct's json tags; correct the struct
  2. If the provider legitimately varies the shape (object vs array), unmarshal into json.RawMessage first and branch on the first non-space byte
  3. Pin the driver to a known-good provider API version if the platform offers versioned endpoints

Example fix

// before
if err := json.Unmarshal(resp.Result, out); err != nil {
	return fmt.Errorf("decode darkibox result failed: %w", err)
}
// after — include endpoint and a body snippet
if err := json.Unmarshal(resp.Result, out); err != nil {
	return fmt.Errorf("decode darkibox result failed for %s: %w (body: %.200s)", endpoint, err, resp.Result)
}
Defensive patterns

Strategy: type-guard

Validate before calling

var probe json.RawMessage
if err := d.callAPI(ctx, endpoint, params, &probe); err == nil {
	if !json.Valid(probe) { return errors.New("provider returned invalid JSON") }
}

Type guard

func isDecodeError(err error) bool {
	return err != nil && strings.Contains(err.Error(), "decode darkibox result failed")
}

Try / catch

if isDecodeError(err) {
	// schema drift: log raw body, fail fast — retrying identical decode will not help
	log.Errorf("schema mismatch: %v", err)
	return err
}

Prevention

When it happens

Trigger: Result is an object where an array was expected (or vice versa) for that endpoint; numeric fields returned as strings; null inside a non-pointer field; provider added/renamed nested fields so types no longer line up with e.g. folderCreateResult or uploadServerResult.

Common situations: After a provider API update changes response casing or nesting; endpoints reused with the wrong result struct; new endpoints whose schema was guessed during driver development.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/fc413d60bfad5889. Report an issue: GitHub.