apache/beam · error
can't apply an alignment period of less than a millisecond.
Error message
can't apply an alignment period of less than a millisecond. Got: %v
What it means
AlignedTo aligns an AfterProcessingTime trigger to multiples of a period; periods below one millisecond cannot be represented in the millisecond-quantized transform, so the method panics. The offset may be a zero time.Time{} and is optional.
Source
Thrown at sdks/go/pkg/beam/core/graph/window/trigger/trigger.go:171
// PlusDelay configures an AfterProcessingTime trigger to fire after a specified delay,
// no smaller than a millisecond.
func (t *AfterProcessingTimeTrigger) PlusDelay(delay time.Duration) *AfterProcessingTimeTrigger {
if delay < time.Millisecond {
panic(fmt.Errorf("can't apply processing delay of less than a millisecond. Got: %v", delay))
}
t.timestampTransforms = append(t.timestampTransforms, DelayTransform{Delay: int64(delay / time.Millisecond)})
return t
}
// AlignedTo configures an AfterProcessingTime trigger to fire
// at the smallest multiple of period since the offset greater than the first element timestamp.
//
// * Period may not be smaller than a millisecond.
// * Offset may be a zero time (time.Time{}).
func (t *AfterProcessingTimeTrigger) AlignedTo(period time.Duration, offset time.Time) *AfterProcessingTimeTrigger {
if period < time.Millisecond {
panic(fmt.Errorf("can't apply an alignment period of less than a millisecond. Got: %v", period))
}
offsetMillis := int64(0)
if !offset.IsZero() {
// TODO: Change to call UnixMilli() once we move to only supporting a go version > 1.17.
offsetMillis = offset.Unix()*1e3 + int64(offset.Nanosecond())/1e6
}
t.timestampTransforms = append(t.timestampTransforms, AlignToTransform{
Period: int64(period / time.Millisecond),
Offset: offsetMillis,
})
return t
}
// RepeatTrigger fires a sub-trigger repeatedly.
type RepeatTrigger struct {
subtrigger Trigger
}
View on GitHub (pinned to 12126d8942)
Solutions
- Pass an alignment period of at least time.Millisecond.
- Clamp the period to time.Millisecond before calling AlignedTo.
- Validate the config value supplying the period (guard against 0).
- For finer alignment granularity, implement a custom trigger rather than using AlignedTo.
Example fix
// before
t := trigger.AfterProcessingTime().AlignedTo(cfg.Period, time.Time{}) // cfg.Period may be 0
// after
p := cfg.Period
if p < time.Millisecond { p = time.Millisecond }
t := trigger.AfterProcessingTime().AlignedTo(p, time.Time{}) Defensive patterns
Strategy: validation
Validate before calling
if period < time.Millisecond { return fmt.Errorf("alignment period must be >= 1ms, got %v", period) } Try / catch
defer func() {
if r := recover(); r != nil {
if strings.Contains(fmt.Sprint(r), "alignment period") { return ErrPeriodTooSmall }
panic(r)
}
}() Prevention
- Validate config values feeding the period (guard against 0)
- Floor the period at time.Millisecond
- Prefer a custom trigger if sub-ms alignment is required
When it happens
Trigger: Calling AlignedTo with period < time.Millisecond, e.g. AlignedTo(100 * time.Microsecond, time.Time{}), or a period computed from config as 0.
Common situations: Unset config value for the alignment period (0 duration); microsecond-level alignment copied from another framework; unit mistakes in duration arithmetic.
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
Related errors
- can't apply processing delay of less than a millisecond. Got
- trigger.AfterCount(%v) must be a positive integer
- AfterProcessingTime trigger set without a delay or alignment
- GroupIntoBatches: %w
- GroupIntoBatchesWithShardedKey: %w
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/64d7f0b95e9ed634.
Report an issue: GitHub.