ISOTime parsing error when fetching epics with date fields

Summary

When fetching epics from the GitLab API using client-go v1.7.0, the library fails to parse date fields (start_date, due_date) with a time parsing error.

Error Message

parsing time "\"2026-06-13T00:00:00+00:00\"" as "\"2006-01-02\"": cannot parse "T00:00:00+00:00\"" as "\""

Environment

  • client-go version: v1.7.0 (also reproduced on v1.6.0 and v0.161.1)
  • Go version: go1.25.4 darwin/arm64
  • OS: macOS (Darwin 25.1.0)
  • GitLab instance: gitlab.com

Minimal Reproduction

package main

import (
	"fmt"
	"log"
	"os"

	"gitlab.com/gitlab-org/api/client-go"
)

func main() {
	token := os.Getenv("GITLAB_TOKEN")
	if token == "" {
		log.Fatal("GITLAB_TOKEN environment variable required")
	}

	client, err := gitlab.NewClient(token)
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	labels := gitlab.LabelOptions{"group::code review"}
	opt := &gitlab.ListGroupEpicsOptions{
		Labels: &labels,
		ListOptions: gitlab.ListOptions{
			PerPage: 5,
			Page:    1,
		},
	}

	epics, _, err := client.Epics.ListGroupEpics("9970", opt)
	if err != nil {
		log.Fatalf("ERROR: %v", err)
	}

	fmt.Printf("Success! Fetched %d epics\n", len(epics))
}

Run:

GITLAB_TOKEN=your_token go run main.go

Result:

2025/12/06 16:46:10 ERROR: parsing time "\"2026-06-13T00:00:00+00:00\"" as "\"2006-01-02\"": cannot parse "T00:00:00+00:00\"" as "\""

Expected Behavior

The library should successfully unmarshal epic date fields. Direct testing shows the GitLab API returns dates in ISO 8601 date format: "2026-06-13".

Investigation

API Returns Correct Format

Direct API call shows proper date format:

curl -H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  "https://gitlab.com/api/v4/groups/9970/epics?labels=group::code%20review&per_page=1" \
  | jq '.[0] | {start_date, due_date}'

Response:

{
  "start_date": "2026-06-13",
  "due_date": "2026-07-10"
}

Raw HTTP Works

Using Go's standard net/http and encoding/json successfully unmarshals the same response without errors:

resp, _ := http.Get(url)
body, _ := io.ReadAll(resp.Body)
var epics []map[string]interface{}
json.Unmarshal(body, &epics)
// epics[0]["start_date"] = "2026-06-13" (type: string)

Analysis

The error message suggests the library is receiving data with:

  • Literal escaped quotes: "\"2026-06-13...\""
  • Full timestamp instead of date: T00:00:00+00:00

But the API returns simple date strings. This suggests an issue in the HTTP client chain or ISOTime.UnmarshalJSON implementation.

Workaround

Using a custom struct with *string for dates instead of *gitlab.ISOTime:

type CustomEpic struct {
    ID        int64    `json:"id"`
    StartDate *string  `json:"start_date"`  // Use string instead of *gitlab.ISOTime
    DueDate   *string  `json:"due_date"`
    // ... other fields
}

req, _ := client.NewRequest("GET", "groups/9970/epics", opt, nil)
var epics []*CustomEpic
client.Do(req, &epics)  // This works!

Additional Notes

  • Affects all tested versions (v0.161.1, v1.6.0, v1.7.0)
  • Only affects epics with non-null date values
  • Raw HTTP requests work correctly, suggesting the issue is in the client library's HTTP/JSON processing