{"record":{"id":"044c5937f3b7e7e8","repo":"gastownhall/beads","slug":"failed-to-create-project-w","errorCode":null,"errorMessage":"failed to create project: %w","messagePattern":"failed to create project: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/linear/client.go","lineNumber":1534,"sourceCode":"\t\t\"teamIds\":     []string{c.TeamID},\n\t\t\"name\":        name,\n\t\t\"description\": description,\n\t}\n\n\tif state != \"\" {\n\t\tinput[\"state\"] = state\n\t}\n\n\treq := &GraphQLRequest{\n\t\tQuery: query,\n\t\tVariables: map[string]interface{}{\n\t\t\t\"input\": input,\n\t\t},\n\t}\n\n\tdata, err := c.Execute(ctx, req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create project: %w\", err)\n\t}\n\n\tvar createResp ProjectCreateResponse\n\tif err := json.Unmarshal(data, &createResp); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse create project response: %w\", err)\n\t}\n\n\tif !createResp.ProjectCreate.Success {\n\t\treturn nil, fmt.Errorf(\"project creation reported as unsuccessful\")\n\t}\n\n\treturn &createResp.ProjectCreate.Project, nil\n}\n\n// UpdateProject updates an existing project in Linear.\nfunc (c *Client) UpdateProject(ctx context.Context, projectID string, updates map[string]interface{}) (*Project, error) {\n\tquery := `\n\t\tmutation UpdateProject($id: String!, $input: ProjectUpdateInput!) {","sourceCodeStart":1516,"sourceCodeEnd":1552,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/linear/client.go#L1516-L1552","documentation":"CreateProject sends a projectCreate mutation with a ProjectCreateInput (teamIds, name, description, optional state). This error wraps any Execute failure: transport error, HTTP error, or GraphQL error from Linear (validation, permissions, unknown team ID). The project is not created when this fires.","triggerScenarios":"c.Execute fails on the mutation: API token lacks project create permission, c.TeamID is invalid or from another workspace, name/description violates Linear validation (length/required), unknown enum value passed as `state`, network failure, or ctx cancellation.","commonSituations":"Bot token with read-only scopes used in automation; team configured incorrectly so teamIds contains a nonexistent ID; passing state values not accepted by ProjectCreateInput; transient network failure during CI sync jobs.","solutions":["Unwrap the error — GraphQL validation messages name the offending input field.","Confirm the API token has project create permission for the target team.","Verify c.TeamID is a real team in the workspace (via FetchTeams).","If passing state, use only values Linear accepts for ProjectCreateInput (planned, started, completed, canceled...); otherwise omit it.","Retry on transient transport errors; the mutation is not idempotent, so check for a created project before retrying to avoid duplicates."],"exampleFix":"// before\ninput[\"state\"] = \"in-progress\" // invalid for ProjectCreateInput\n_, err := client.CreateProject(ctx, name, desc, \"in-progress\")\n// after\n// omit state or use a valid enum\n_, err := client.CreateProject(ctx, name, desc, \"\") // state omitted when empty","handlingStrategy":"validation","validationCode":"// pre-flight before CreateProject\nif name == \"\" || len(name) > 255 {\n    return fmt.Errorf(\"project name required and <=255 chars\")\n}\nif client.TeamID == \"\" {\n    return fmt.Errorf(\"TeamID not configured; run FetchTeams first\")\n}\nvalidProjectStates := map[string]bool{\"planned\":true,\"started\":true,\"completed\":true,\"canceled\":true,\"\":true}\nif !validProjectStates[state] {\n    return fmt.Errorf(\"invalid project state %q\", state)\n}","typeGuard":null,"tryCatchPattern":"project, err := client.CreateProject(ctx, name, desc, state)\nif err != nil {\n    if strings.Contains(err.Error(), \"permission\") || strings.Contains(err.Error(), \"403\") {\n        return fmt.Errorf(\"token lacks project create scope: %w\", err)\n    }\n    if isNetworkErr(err) {\n        // check whether the project was actually created before retrying (avoid duplicates)\n        return findOrCreateProject(ctx, client, name, desc, state)\n    }\n    return err\n}","preventionTips":["Verify token scopes include project create before automation runs.","Resolve TeamID via FetchTeams instead of hardcoding.","Omit state unless you need a non-default value; empty string is safely skipped by the client.","Don't blind-retry the mutation on transport errors — search by name first to avoid duplicate projects."],"tags":["go","graphql","mutation","linear-api"],"backgroundTag":"graphql-mutation-rejected","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}