gastownhall/beads · error

failed to parse work item states value: %w

Error message

failed to parse work item states value: %w

What it means

GetWorkItemStates fetched the list of valid states for a work item type from Azure DevOps, but the JSON 'value' array inside the response envelope could not be unmarshaled into []WorkItemState. The HTTP call succeeded, but the response body did not have the expected shape (envelope.value must be a JSON array of state objects with expected field types). This guards callers from a silently nil/partial states list.

Source

Thrown at internal/ado/client.go:622

	return types, nil
}

// GetWorkItemStates returns the states for a given work item type.
func (c *Client) GetWorkItemStates(ctx context.Context, typeName string) ([]WorkItemState, error) {
	urlStr := addAPIVersion(c.apiBase() + "/wit/workitemtypes/" + url.PathEscape(typeName) + "/states")
	respBody, err := c.doRequest(ctx, http.MethodGet, urlStr, "", nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get work item states: %w", err)
	}

	var envelope listResponse
	if err := json.Unmarshal(respBody, &envelope); err != nil {
		return nil, fmt.Errorf("failed to parse work item states response: %w", err)
	}

	var states []WorkItemState
	if err := json.Unmarshal(envelope.Value, &states); err != nil {
		return nil, fmt.Errorf("failed to parse work item states value: %w", err)
	}
	return states, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Verify the organization URL and API version used by the ADO client match a supported Azure DevOps REST version (check ado.url / AZURE_DEVOPS_URL).
  2. Log/curl the raw response of GET {org}/{project}/_apis/wit/workitemtypes/{type}/states?api-version=... and compare its 'value' entries to the WorkItemState struct field types.
  3. If behind a proxy or mock, fix the mock to return {"count":N,"value":[{"name":..., "category":..., ...}]}.
  4. Update the library if Azure DevOps changed the states payload schema.

Example fix

// before: assuming any 200 body is the states envelope
// after: log the raw body when unmarshal fails
if err := json.Unmarshal(envelope.Value, &states); err != nil {
    return nil, fmt.Errorf("failed to parse work item states value: %w (body: %.200s)", err, envelope.Value)
}
Defensive patterns

Strategy: validation

Validate before calling

resp, _ := http.Get(statesURL)
body, _ := io.ReadAll(resp.Body)
var probe struct {
    Value []map[string]json.RawMessage `json:"value"`
}
if json.Unmarshal(body, &probe) != nil || len(probe.Value) == 0 && resp.StatusCode == 200 {
    return fmt.Errorf("states endpoint returned unexpected payload")
}

Type guard

func isValidStatesEnvelope(body []byte) bool {
    var env struct {
        Value json.RawMessage `json:"value"`
    }
    if json.Unmarshal(body, &env) != nil {
        return false
    }
    var states []map[string]interface{}
    return json.Unmarshal(env.Value, &states) == nil
}

Try / catch

states, err := client.GetWorkItemStates(ctx, project, wit)
if err != nil {
    var parseErr *json.UnmarshalTypeError
    if errors.As(err, &parseErr) {
        log.Printf("ADO states payload shape changed: field %s", parseErr.Field)
        return fallbackDefaultStates(wit)
    }
    return err
}

Prevention

When it happens

Trigger: Calling GetWorkItemStates against an ADO organization/process whose response 'value' field is not an array of objects matching the WorkItemState struct (e.g. wrong field types like name as object, or value being a single object).

Common situations: Pointing ado.url at a proxy/mocked ADO endpoint that returns differently shaped JSON; ADO API version changes altering the states payload; hitting a custom inherited process endpoint that returns extra/renamed fields with incompatible types; misconfigured org URL returning an HTML error page for the states route.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/8cbfcc0185fe644c. Report an issue: GitHub.