{"record":{"id":"df8d02f0ec4604b2","repo":"temporalio/temporal","slug":"second-value-out-of-range-v","errorCode":null,"errorMessage":"second value out of range: %v","messagePattern":"second value out of range: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"common/nexus/nexusrpc/timestamp.go","lineNumber":36,"sourceCode":"\tx := t.UTC().Format(\"2006-01-02T15:04:05.000000000\")\n\tx = strings.TrimSuffix(x, \"000\")\n\tx = strings.TrimSuffix(x, \"000\")\n\tx = strings.TrimSuffix(x, \".000\")\n\treturn x + \"Z\"\n}\n\n// unmarshalTimestamp unmarshals a string into a Time instance. Uses RFC 3339, with some extra validation to ensure that\n// seconds and subseconds are with an expected range.\n// Copied from https://github.com/protocolbuffers/protobuf-go/blob/0b2c87d84c27802dae7248480444e22421ba577d/encoding/protojson/well_known_types.go#L749C1-L826C2\nfunc unmarshalTimestamp(s string) (time.Time, error) {\n\tt, err := time.Parse(time.RFC3339Nano, s)\n\tif err != nil {\n\t\treturn t, err\n\t}\n\t// Validate seconds.\n\tsecs := t.Unix()\n\tif secs < minTimestampSeconds || secs > maxTimestampSeconds {\n\t\treturn t, fmt.Errorf(\"second value out of range: %v\", secs)\n\t}\n\t// Validate subseconds.\n\ti := strings.LastIndexByte(s, '.')  // start of subsecond field\n\tj := strings.LastIndexAny(s, \"Z-+\") // start of timezone field\n\tif i >= 0 && j >= i && j-i > len(\".999999999\") {\n\t\treturn t, fmt.Errorf(\"invalid subsecond value %v\", s)\n\t}\n\treturn t, nil\n}\n","sourceCodeStart":18,"sourceCodeEnd":46,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/nexus/nexusrpc/timestamp.go#L18-L46","documentation":"unmarshalTimestamp parses RFC 3339 timestamps used in Nexus HTTP headers and defensively bounds the parsed time to minTimestampSeconds..maxTimestampSeconds. If the resulting Unix seconds fall outside that range (e.g. year far in the past or future), it rejects the value with this error to prevent overflow downstream (e.g. when converting to duration or milliseconds).","triggerScenarios":"A client sends a timestamp header with an extreme value — e.g. year 0001 or year 9999, or a bogus huge year — which parses as valid RFC 3339 but whose Unix seconds exceed the bounds, from ServeHTTP.","commonSituations":"Buggy clients constructing timestamps from zero-valued time.Time (year 1); clock misconfiguration; hand-crafted or fuzzed HTTP requests with adversarial headers.","solutions":["Fix the producer to emit current-time RFC 3339 timestamps (time.Now().UTC().Format(time.RFC3339Nano)).","Check for zero-value time.Time being formatted accidentally and guard against it.","If a legitimate use needs a wider range, adjust min/maxTimestampSeconds consciously.","Reject/log the request at the edge with a 400 before deeper processing."],"exampleFix":"// before\nheader.Set(\"request-time\", t.Format(time.RFC3339Nano)) // t is zero value -> year 1 -> out of range\n// after\nif t.IsZero() {\n    t = time.Now().UTC()\n}\nheader.Set(\"request-time\", t.Format(time.RFC3339Nano))","handlingStrategy":"validation","validationCode":"secs := t.Unix()\nif t.IsZero() || secs < minTimestampSeconds || secs > maxTimestampSeconds {\n    return errors.New(\"timestamp out of supported range\")\n}","typeGuard":"func validTimestamp(t time.Time) bool {\n    return !t.IsZero() && t.Year() >= 1 && t.Year() <= 9999 && t.Unix() >= minTimestampSeconds && t.Unix() <= maxTimestampSeconds\n}","tryCatchPattern":"t, err := time.Parse(time.RFC3339Nano, raw)\nif err != nil || t.IsZero() {\n    return fmt.Errorf(\"invalid request-time header: %w\", err)\n}","preventionTips":["Always emit timestamps from time.Now().UTC().Format(time.RFC3339Nano)","Guard against zero-value time.Time being formatted into headers","Validate timestamp headers at the edge of your service before deep processing","Never hand-concatenate timestamp strings in clients"],"tags":["nexus","timestamp","validation","http-header"],"backgroundTag":"timestamp-out-of-range","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}