{"record":{"id":"f5445ba42c80c08d","repo":"gastownhall/beads","slug":"failed-to-parse-projects-value-w","errorCode":null,"errorMessage":"failed to parse projects value: %w","messagePattern":"failed to parse projects value: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/ado/client.go","lineNumber":582,"sourceCode":"}\n\n// ListProjects returns all team projects in the organization.\n// This is an org-level endpoint, not project-scoped.\nfunc (c *Client) ListProjects(ctx context.Context) ([]Project, error) {\n\turlStr := addAPIVersion(c.orgBase() + \"/projects\")\n\trespBody, err := c.doRequest(ctx, http.MethodGet, urlStr, \"\", nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to list projects: %w\", err)\n\t}\n\n\tvar envelope listResponse\n\tif err := json.Unmarshal(respBody, &envelope); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse projects response: %w\", err)\n\t}\n\n\tvar projects []Project\n\tif err := json.Unmarshal(envelope.Value, &projects); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse projects value: %w\", err)\n\t}\n\treturn projects, nil\n}\n\n// GetWorkItemTypes returns the work item types available in the project.\nfunc (c *Client) GetWorkItemTypes(ctx context.Context) ([]WorkItemType, error) {\n\turlStr := addAPIVersion(c.apiBase() + \"/wit/workitemtypes\")\n\trespBody, err := c.doRequest(ctx, http.MethodGet, urlStr, \"\", nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get work item types: %w\", err)\n\t}\n\n\tvar envelope listResponse\n\tif err := json.Unmarshal(respBody, &envelope); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse work item types response: %w\", err)\n\t}\n\n\tvar types []WorkItemType","sourceCodeStart":564,"sourceCodeEnd":600,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/ado/client.go#L564-L600","documentation":"This error means the list envelope decoded but the nested 'value' field could not be unmarshalled into []Project. The top-level JSON looked right, but the items inside 'value' do not match the Project struct (unexpected field types or 'value' not an array).","triggerScenarios":"Calling ListProjects when ADO's projects payload has items whose fields don't match the Project struct's types (e.g. an 'id' that isn't a string, or 'value' being an object/null instead of an array) — typically after an API version change or schema drift.","commonSituations":"ADO rolling out an API response change; using an api-version whose schema differs from what the library expects; mocking proxies (e.g. recorded fixtures) returning differently-typed fields.","solutions":["Inspect envelope.Value raw JSON and compare against the library's Project struct field types","Pin/check the api-version the library sends (addAPIVersion) against ADO's current projects schema","Upgrade the ado package to a version matching the current ADO response schema","If using a mock/proxy for tests, fix the fixture so 'value' is an array of Project-shaped objects"],"exampleFix":"// before (fixture)\n{\"value\": {\"id\": 1, \"name\": \"p\"}}\n// after\n{\"count\": 1, \"value\": [{\"id\": \"abcd-...\", \"name\": \"p\"}]}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// validate a projects payload shape before trusting it\ntype listEnvelope struct {\n  Count int             `json:\"count\"`\n  Value json.RawMessage `json:\"value\"`\n}\nfunc projectsPayloadOK(body []byte) bool {\n  var env listEnvelope\n  if json.Unmarshal(body, &env) != nil || env.Value == nil {\n    return false\n  }\n  var arr []map[string]any\n  return json.Unmarshal(env.Value, &arr) == nil\n}","tryCatchPattern":"projects, err := client.ListProjects(ctx)\nif err != nil {\n  if strings.Contains(err.Error(), \"failed to parse projects value\") {\n    return nil, fmt.Errorf(\"ADO projects schema drift — check api-version/library version: %w\", err)\n  }\n  return nil, err\n}","preventionTips":["Pin the ADO api-version expected by the library version you deploy","Keep test fixtures in sync with real ADO payloads","Upgrade the ado package when ADO announces schema changes","Validate 'value' is an array of object-shaped items in mocks"],"tags":["json","parsing","azure-devops","schema-mismatch"],"backgroundTag":"json-decode-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}