{"record":{"id":"d6e8b29677aefd2d","repo":"gastownhall/beads","slug":"transitioning-to-intermediate-state-q-w","errorCode":null,"errorMessage":"transitioning to intermediate state %q: %w","messagePattern":"transitioning to intermediate state %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/ado/statetransition.go","lineNumber":135,"sourceCode":"\t// through intermediate states. Any other error is a real failure.\n\tvar apiErr *APIError\n\tif !errors.As(err, &apiErr) || apiErr.StatusCode != http.StatusBadRequest {\n\t\treturn nil, fmt.Errorf(\"transitioning to %q: %w\", targetState, err)\n\t}\n\n\tpath := resolveTransitionPath(workItemType, currentState, targetState)\n\tif len(path) == 0 {\n\t\treturn nil, fmt.Errorf(\"no known transition path from %q to %q for %s: %w\",\n\t\t\tcurrentState, targetState, workItemType, err)\n\t}\n\n\t// Walk through intermediate states.\n\tvar lastWI *WorkItem\n\tfor _, intermediate := range path {\n\t\tfields := map[string]interface{}{FieldState: intermediate}\n\t\tlastWI, err = c.UpdateWorkItem(ctx, workItemID, fields)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"transitioning to intermediate state %q: %w\", intermediate, err)\n\t\t}\n\t}\n\treturn lastWI, nil\n}\n","sourceCodeStart":117,"sourceCodeEnd":140,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/ado/statetransition.go#L117-L140","documentation":"When a direct state change returns 400 and a multi-hop path exists, transitionWorkItem walks through intermediate states, calling UpdateWorkItem for each. If an intermediate hop fails, the error is wrapped as 'transitioning to intermediate state \"<state>\"' and the walk aborts; the work item may be left in the last successfully reached intermediate state.","triggerScenarios":"UpdateWorkItem for an intermediate hop returns 401/403, 404, 409 (conflict/stale revision), 500, or even 400 (a rule on the intermediate state blocks the change, e.g. required fields like Microsoft.VSTS.Common.ActivatedDate must be set when moving to Active).","commonSituations":"ADO process rules requiring fields (assigned-to, iteration path) on the intermediate state; concurrent edits bumping the revision; PAT permissions; ADO outage mid-walk.","solutions":["Read the inner error: if 400, check ADO work item type rules that require fields on the intermediate state and set them via UpdateWorkItem alongside the state change.","Refresh the work item before re-running to clear 409 revision conflicts.","Fix PAT write permissions for 401/403.","Re-run the transition: after the partial walk the current state is a valid intermediate, so direct or shorter-path transitions may now succeed."],"exampleFix":"// before: only setting state on intermediate hops\nfields := map[string]interface{}{FieldState: intermediate}\nlastWI, err = c.UpdateWorkItem(ctx, workItemID, fields)\n// after: include rule-required fields for the intermediate state\nfields := map[string]interface{}{\n    FieldState: intermediate,\n    \"System.AssignedTo\": assignee, // satisfies rules like 'must be assigned when Active'\n}\nlastWI, err = c.UpdateWorkItem(ctx, workItemID, fields)","handlingStrategy":"try-catch","validationCode":"// Check required-field rules by inspecting the item before intermediate hops\nwi, _, err := client.GetWorkItem(ctx, workItemID, nil)\nif err == nil && intermediate == \"Active\" {\n    if wi.Fields[\"System.AssignedTo\"] == nil {\n        return fmt.Errorf(\"set System.AssignedTo before moving to Active (process rule)\")\n    }\n}","typeGuard":"func isIntermediateHopFailure(err error) (string, bool) {\n    m := regexp.MustCompile(`transitioning to intermediate state \"([^\"]+)\"`).FindStringSubmatch(err.Error())\n    if len(m) < 2 { return \"\", false }\n    return m[1], true\n}","tryCatchPattern":"wi, err := client.TransitionWorkItem(ctx, id, target)\nif err != nil {\n    if state, ok := isIntermediateHopFailure(err); ok {\n        log.Printf(\"walk stopped at intermediate state %q; item may need required fields set there\", state)\n        // recover: refresh item and either set fields or accept the current state\n    }\n    return err\n}","preventionTips":["Populate rule-required fields (assignee, dates, iteration) when walking through states like Active/Resolved.","Refresh the work item before the walk to avoid revision-conflict 409s.","Test the transition path against your ADO process in a sandbox project.","Handle partial walks: after failure the item is in a valid intermediate state; re-running resumes from there."],"tags":["azure-devops","state-transition","http-error","process-rules"],"backgroundTag":"invalid-state-transition","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}