{"record":{"id":"3b7640653a0e2308","repo":"apache/beam","slug":"can-t-apply-processing-delay-of-less-than-a-millisecond-got","errorCode":null,"errorMessage":"can't apply processing delay of less than a millisecond. Got: %v","messagePattern":"can't apply processing delay of less than a millisecond\\. Got: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/graph/window/trigger/trigger.go","lineNumber":158,"sourceCode":"// Eg. A period of 20 with an offset of 45 would have alignments at 5,25,45,65 etc.\n// Timestamps would be transformed as follows: 0 to 5 would be transformed to 5,\n// 6 to 25 would be transformed to 25, 26 to 45 would be transformed to 45, and so on.\ntype AlignToTransform struct {\n\tPeriod, Offset int64 // in milliseconds\n}\n\n// String implements the Stringer interface and returns trigger details as a string.\nfunc (t *AlignToTransform) String() string {\n\treturn fmt.Sprintf(\"%#v\", t)\n}\n\nfunc (AlignToTransform) timestampTransform() {}\n\n// PlusDelay configures an AfterProcessingTime trigger to fire after a specified delay,\n// no smaller than a millisecond.\nfunc (t *AfterProcessingTimeTrigger) PlusDelay(delay time.Duration) *AfterProcessingTimeTrigger {\n\tif delay < time.Millisecond {\n\t\tpanic(fmt.Errorf(\"can't apply processing delay of less than a millisecond. Got: %v\", delay))\n\t}\n\tt.timestampTransforms = append(t.timestampTransforms, DelayTransform{Delay: int64(delay / time.Millisecond)})\n\treturn t\n}\n\n// AlignedTo configures an AfterProcessingTime trigger to fire\n// at the smallest multiple of period since the offset greater than the first element timestamp.\n//\n// * Period may not be smaller than a millisecond.\n// * Offset may be a zero time (time.Time{}).\nfunc (t *AfterProcessingTimeTrigger) AlignedTo(period time.Duration, offset time.Time) *AfterProcessingTimeTrigger {\n\tif period < time.Millisecond {\n\t\tpanic(fmt.Errorf(\"can't apply an alignment period of less than a millisecond. Got: %v\", period))\n\t}\n\toffsetMillis := int64(0)\n\tif !offset.IsZero() {\n\t\t// TODO: Change to call UnixMilli() once we move to only supporting a go version > 1.17.\n\t\toffsetMillis = offset.Unix()*1e3 + int64(offset.Nanosecond())/1e6","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/graph/window/trigger/trigger.go#L140-L176","documentation":"AfterProcessingTime triggers quantize delays to whole milliseconds, so PlusDelay rejects delays smaller than one millisecond by panicking. This enforces the documented minimum resolution of processing-time trigger transforms.","triggerScenarios":"Calling PlusDelay with a duration below time.Millisecond, e.g. PlusDelay(500 * time.Microsecond) or a sub-millisecond value computed at runtime.","commonSituations":"Using nanosecond/microsecond constants intended for other timing APIs; arithmetic on durations (like dividing a second by 10000) producing sub-ms values; porting code from systems with finer trigger resolution.","solutions":["Use a delay of at least time.Millisecond.","Clamp the computed delay to time.Millisecond as a floor before calling PlusDelay.","If sub-millisecond timing is truly required, this trigger API cannot support it; redesign around a coarser granularity.","Verify duration arithmetic units (ns-based time.Duration values are easily mis-scaled)."],"exampleFix":"// before\nt := trigger.AfterProcessingTime().PlusDelay(500 * time.Microsecond)\n// after\nd := 500 * time.Microsecond\nif d < time.Millisecond { d = time.Millisecond }\nt := trigger.AfterProcessingTime().PlusDelay(d)","handlingStrategy":"validation","validationCode":"if delay < time.Millisecond { return fmt.Errorf(\"delay must be >= 1ms, got %v\", delay) }","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        if strings.Contains(fmt.Sprint(r), \"processing delay\") { return ErrDelayTooSmall }\n        panic(r)\n    }\n}()","preventionTips":["Floor computed delays at time.Millisecond","Watch time.Duration unit arithmetic (values are nanoseconds)","Note the API's documented millisecond minimum"],"tags":["go","apache-beam","trigger","panic","duration"],"backgroundTag":"invalid-duration-format","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}