vectordotdev/vector · warning

unable to compute next deadline

Error message

unable to compute next deadline

What it means

The file sink schedules idle flush deadlines by adding its idle_timeout Duration to the current Instant. Instant::checked_add returns None on overflow (only possible on platforms with small Instant ranges or absurdly large idle_timeout), and the expect panics 'unable to compute next deadline'.

Solutions

  1. Set a reasonable idle_timeout value (seconds/minutes) in the file sink config
  2. Use checked_add and handle None by falling back to a far-future instant
  3. Cap idle_timeout at config validation time

Example fix

// before
Instant::now().checked_add(self.idle_timeout).expect("unable to compute next deadline")
// after
Instant::now().checked_add(self.idle_timeout).unwrap_or_else(Instant::far_future)
Defensive patterns

Strategy: fallback

Validate before calling

// rust: sanity-check the duration at config load
assert!(idle_timeout <= Duration::from_secs(30*24*3600), "idle_timeout too large");

Type guard

fn fits_instant(d: Duration) -> bool { Instant::now().checked_add(d).is_some() }

Try / catch

let deadline = Instant::now().checked_add(self.idle_timeout).unwrap_or_else(Instant::far_future);

Prevention

When it happens

Trigger: deadline_at() is invoked with an idle_timeout so large that Instant::now() + idle_timeout overflows the platform's Instant representation.

Common situations: Configuration with an enormous idle_timeout (e.g. centuries in human-readable config); exotic platforms with narrow time representations.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16). Data as JSON: /api/errors/22fc893dc9727883. Report an issue: GitHub.

Appendix: source

Thrown at src/sinks/file/mod.rs:415

                Ok(normalized) => Some(path_to_bytes(&normalized)),
                Err(error) => {
                    emit!(FilePathOutsideBaseDirError {
                        path: &rendered_path,
                        base_dir: confinement.base_dir(),
                        error,
                    });
                    None
                }
            }
        } else {
            Some(bytes)
        }
    }

    fn deadline_at(&self) -> Instant {
        Instant::now()
            .checked_add(self.idle_timeout)
            .expect("unable to compute next deadline")
    }

    async fn run(&mut self, mut input: BoxStream<'_, Event>) -> crate::Result<()> {
        loop {
            tokio::select! {
                event = input.next() => {
                    match event {
                        Some(event) => self.process_event(event).await,
                        None => {
                            // If we got `None` - terminate the processing.
                            debug!(message = "Receiver exhausted, terminating the processing loop.");

                            // Close all the open files.
                            debug!(message = "Closing all the open files.");
                            for (path, file) in self.files.iter_mut() {
                                if let Err(error) = file.close().await {
                                    emit!(FileIoError {
                                        error,

View on GitHub (pinned to bdb87aeaa4)