{"record":{"id":"02addc0f19476f0d","repo":"amir20/dozzle","slug":"invalid-start-time-format-expected-rfc3339-w","errorCode":null,"errorMessage":"invalid start time format (expected RFC3339): %w","messagePattern":"invalid start time format \\(expected RFC3339\\): %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloud/tools_logs.go","lineNumber":45,"sourceCode":"\tif err := json.Unmarshal([]byte(argsJSON), &args); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse arguments: %w\", err)\n\t}\n\thostID, containerID, note, err := resolveContainerRefRead(args.ContainerID, args.Host, deps)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcs, err := deps.HostService.FindContainer(hostID, containerID, deps.Labels)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"container not found: %w\", err)\n\t}\n\n\tstart := time.Now().Add(-1 * time.Hour)\n\tend := time.Now()\n\tif args.Start != \"\" {\n\t\tt, err := time.Parse(time.RFC3339, args.Start)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid start time format (expected RFC3339): %w\", err)\n\t\t}\n\t\tstart = t\n\t}\n\tif args.End != \"\" {\n\t\tt, err := time.Parse(time.RFC3339, args.End)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid end time format (expected RFC3339): %w\", err)\n\t\t}\n\t\tend = t\n\t}\n\n\tvar re *regexp.Regexp\n\tif args.Regex != \"\" {\n\t\tvar err error\n\t\tre, err = regexp.Compile(args.Regex)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid regex pattern: %w\", err)\n\t\t}","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/amir20/dozzle/blob/d9463cbe21874e44ab79db6fa63e746ca7d22928/internal/cloud/tools_logs.go#L27-L63","documentation":"executeFetchContainerLogs parses the optional start argument with time.Parse(time.RFC3339, ...). When the string is present but not a valid RFC3339 timestamp, the underlying parse error is wrapped as 'invalid start time format (expected RFC3339)' and returned as a tool-call failure. This is strict input validation on the log-fetch tool's date range.","triggerScenarios":"Calling the fetch_container_logs cloud tool with args.start set to a non-RFC3339 value such as '1h ago', '2024-01-01', '1700000000' (unix seconds), or a timestamp missing timezone info like '2024-01-01T10:00:00'.","commonSituations":"LLM tool callers passing human-readable relative times instead of ISO timestamps; clients generating timestamps without timezone offsets; code constructing dates with date.toString() instead of toISOString().","solutions":["Pass the start time as RFC3339 with timezone, e.g. 2024-05-01T10:00:00Z","Omit the start argument entirely (it defaults to one hour ago)","Normalize relative expressions ('1h ago') to absolute RFC3339 before calling the tool"],"exampleFix":"// before\n{\"container_id\":\"abc\",\"start\":\"1 hour ago\"}\n// after\n{\"container_id\":\"abc\",\"start\":\"2024-05-01T09:00:00Z\"}","handlingStrategy":"validation","validationCode":"function isValidRFC3339(s) { if (!s) return true; return /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})$/.test(s) && !isNaN(Date.parse(s)); }\nif (args.start && !isValidRFC3339(args.start)) args.start = new Date(Date.now() - 3600e3).toISOString();","typeGuard":"null","tryCatchPattern":null,"preventionTips":["Always emit timestamps via toISOString() or RFC3339 formatters","Never pass relative times or unix epochs as start","Omit the field when you want the one-hour default"],"tags":["cloud-tools","time-parsing","validation"],"backgroundTag":"invalid-date-format","analyzedSha":"d9463cbe21874e44ab79db6fa63e746ca7d22928","analyzedAt":"2026-09-07T10:08:55.855Z","contentChangedAt":"2026-09-07T10:08:55.855Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}