gastownhall/beads · error
failed to parse create response: %w
Error message
failed to parse create response: %w
What it means
CreateIssue received a response it could not decode into a single Issue object. The HTTP call succeeded but the body was not the expected JSON issue payload.
Source
Thrown at internal/gitlab/client.go:358
// CreateIssue creates a new issue in GitLab.
func (c *Client) CreateIssue(ctx context.Context, title, description string, labels []string) (*Issue, error) {
body := map[string]interface{}{
"title": title,
"description": description,
}
if len(labels) > 0 {
body["labels"] = labels
}
urlStr := c.buildURL("/projects/"+c.projectPath()+"/issues", nil)
respBody, _, err := c.doRequest(ctx, http.MethodPost, urlStr, body)
if err != nil {
return nil, fmt.Errorf("failed to create issue: %w", err)
}
var issue Issue
if err := json.Unmarshal(respBody, &issue); err != nil {
return nil, fmt.Errorf("failed to parse create response: %w", err)
}
return &issue, nil
}
// UpdateIssue updates an existing issue in GitLab.
func (c *Client) UpdateIssue(ctx context.Context, iid int, updates map[string]interface{}) (*Issue, error) {
urlStr := c.buildURL("/projects/"+c.projectPath()+"/issues/"+strconv.Itoa(iid), nil)
respBody, _, err := c.doRequest(ctx, http.MethodPut, urlStr, updates)
if err != nil {
return nil, fmt.Errorf("failed to update issue: %w", err)
}
var issue Issue
if err := json.Unmarshal(respBody, &issue); err != nil {
return nil, fmt.Errorf("failed to parse update response: %w", err)
}
View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the raw response body (log respBody on parse failure) and the wrapped Unmarshal error
- Compare the failing field against the Issue struct and update the library or struct for your GitLab version
- Verify the endpoint is the real GitLab API (no interception)
- Pin library version to your server's GitLab version
Example fix
// before
issue, err := client.CreateIssue(ctx, title, desc, labels)
// after
issue, err := client.CreateIssue(ctx, title, desc, labels)
if err != nil {
log.Printf("create failed (resp body may differ from Issue schema): %v", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
resp, _ := http.Post(baseURL+"/api/v4/projects/"+proj+"/issues", "application/json", bodyReader)
ct := resp.Header.Get("Content-Type")
if !strings.Contains(ct, "application/json") {
return fmt.Errorf("unexpected content type %q; endpoint may be intercepted", ct)
} Type guard
func isParseCreateErr(err error) bool {
return strings.Contains(err.Error(), "failed to parse create response")
} Try / catch
issue, err := client.CreateIssue(ctx, title, desc, labels)
if err != nil {
if isParseCreateErr(err) {
log.Printf("create succeeded at server? verify manually; response unparseable: %v", err)
}
return err
} Prevention
- Remove API-rewriting proxies/gateways from the path
- Keep library and GitLab server versions compatible
- On parse failure, check the server for duplicate issues before retrying (the create may have succeeded)
- Log raw response bodies for post-mortem
When it happens
Trigger: POST /projects/:id/issues returns a non-issue JSON body — e.g. an error object (as JSON with 200 from a proxy), an HTML page, or GitLab schema drift making a field's type incompatible with the Issue struct.
Common situations: API gateways returning JSON error envelopes, GitLab upgrades changing field types, or pointing the client at a non-GitLab endpoint that echoes JSON.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse issues response: %w
- failed to parse update response: %w
- failed to parse issue links response: %w
- failed to marshal request body: %w
- request failed (attempt %d/%d): %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/8bf26e9db1ebf27c.
Report an issue: GitHub.