{"record":{"id":"382ec52a15f1a357","repo":"gastownhall/beads","slug":"project-creation-reported-as-unsuccessful","errorCode":null,"errorMessage":"project creation reported as unsuccessful","messagePattern":"project creation reported as unsuccessful","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/linear/client.go","lineNumber":1543,"sourceCode":"\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!) {\n\t\t\tprojectUpdate(id: $id, input: $input) {\n\t\t\t\tsuccess\n\t\t\t\tproject {\n\t\t\t\t\tid\n\t\t\t\t\tname\n\t\t\t\t\tdescription\n\t\t\t\t\tslugId\n\t\t\t\t\turl\n\t\t\t\t\tstate","sourceCodeStart":1525,"sourceCodeEnd":1561,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/linear/client.go#L1525-L1561","documentation":"CreateProject checks the mutation payload's projectCreate.success boolean after a successful transport call and decode. When Linear reports success=false (with no GraphQL-level error and no unmarshal failure), the library returns this sentinel error. It means Linear accepted and answered the mutation but indicated the project was not created.","triggerScenarios":"Execute succeeded and JSON decoded fine, but createResp.ProjectCreate.Success is false — Linear rejected the mutation at the payload level (e.g. validation the API expressed via success flag, permission checks that don't raise GraphQL errors, or a null project node).","commonSituations":"Token can authenticate but lacks write access to the team; teamIds references a team where project creation is restricted; Linear-side workspace settings block project creation by bots; success flag semantics changed across Linear API versions so the struct reads a stale field.","solutions":["Since this error carries no detail, log the full createResp (or raw data) around the call to see what else the payload contains.","Verify the API token's write permissions for the target team in Linear admin settings.","Confirm teamIds is valid — cross-check c.TeamID with FetchTeams.","Run the identical projectCreate mutation manually (curl/Altair) with the same input to see Linear's full response.","If the payload contains a null project with success=false, check Linear's API changelog for changed projectCreate semantics and update the response struct."],"exampleFix":"// before\nif !createResp.ProjectCreate.Success {\n    return nil, fmt.Errorf(\"project creation reported as unsuccessful\")\n}\n// after (caller side: log payload for diagnosis)\nproject, err := client.CreateProject(ctx, name, desc, state)\nif err != nil && err.Error() == \"project creation reported as unsuccessful\" {\n    log.Printf(\"linear rejected projectCreate for team=%s name=%q; check token scopes/teamId\", client.TeamID, name)\n}","handlingStrategy":"validation","validationCode":"// pre-flight: confirm team and write access before attempting creation\nteams, err := client.FetchTeams(ctx)\nif err != nil { return err }\nfound := false\nfor _, t := range teams {\n    if t.ID == client.TeamID { found = true; break }\n}\nif !found {\n    return fmt.Errorf(\"TeamID %q not visible to this token\", client.TeamID)\n}","typeGuard":"func createSucceeded(resp ProjectCreateResponse) bool {\n    return resp.ProjectCreate.Success && resp.ProjectCreate.Project.ID != \"\"\n}","tryCatchPattern":"project, err := client.CreateProject(ctx, name, desc, state)\nif err != nil && err.Error() == \"project creation reported as unsuccessful\" {\n    // no detail in the error: verify existing projects to avoid duplicates, then surface context\n    existing, _ := client.FetchProjects(ctx, \"all\")\n    for _, p := range existing {\n        if p.Name == name { return &p, nil /* already created */ }\n    }\n    return fmt.Errorf(\"linear rejected projectCreate (team=%s, name=%q): check token scopes\", client.TeamID, name)\n}","preventionTips":["Validate token write scopes and team membership at startup, not at first create.","Cross-check TeamID with FetchTeams before mutations.","Because the sentinel error carries no cause, wrap calls to log the surrounding context (input, team, timestamp).","After a failed create, search FetchProjects by name to detect partial/duplicate creation before retrying.","Track Linear API changelog for changes to projectCreate success semantics."],"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"}