risingwavelabs/risingwave · error · Error

NotFound error

Error message

NotFound error: {0}

What it means

The in-memory object store (crate::object::mem) returns Error::NotFound when a requested object key does not exist in the store. Callers convert it to ObjectError via From, and Error::is_object_not_found_error() recognizes it.

Solutions

  1. Verify the exact key string/path was written before being read (watch for typo or missing leading/trailing separators)
  2. Check that another component did not delete or overwrite the object
  3. In tests, seed the store with the object before the read assertion
  4. If this should be tolerated, use is_object_not_found_error() to branch on it instead of failing

Example fix

// before
let data = mem_store.read(obj_id, None).await?;
// after
match mem_store.read(obj_id, None).await {
    Ok(d) => d,
    Err(e) if e.to_string().starts_with("NotFound error:") => {
        tracing::warn!(object_id = obj_id, "object missing, treating as absent");
        return Ok(None);
    }
    Err(e) => return Err(e.into()),
}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the key exists before reading (mem store supports listing)
let exists = mem_store
    .list(prefix)
    .await?
    .iter()
    .any(|m| m.key == expected_key);
if !exists {
    // treat as absent instead of erroring
}

Type guard

fn is_object_not_found(e: &crate::object::mem::Error) -> bool {
    matches!(e, crate::object::mem::Error::NotFound(_))
}

Try / catch

match mem_store.read(key, None).await {
    Ok(data) => data,
    Err(e) if matches!(e, crate::object::mem::Error::NotFound(_)) => {
        tracing::warn!(key, "object not found in mem store");
        Default::default()
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Reading, getting metadata, or deleting a key from MemObjectStore/MemStreamingUploader state that was never written or has been removed — typically in tests or madsim runs.

Common situations: Unit/integration tests that reference keys before writing them, race conditions where a key is deleted between list and read, madsim-simulated object store missing objects after simulated restarts.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/e50b4947d11d6394. Report an issue: GitHub.

Appendix: source

Thrown at src/object_store/src/object/mem.rs:36

use std::task::{Context, Poll};
use std::time::{SystemTime, UNIX_EPOCH};

use bytes::{BufMut, Bytes, BytesMut};
use fail::fail_point;
use futures::Stream;
use itertools::Itertools;
use risingwave_common::range::RangeBoundsExt;
use thiserror::Error;
use tokio::sync::Mutex;

use super::{
    ObjectError, ObjectMetadata, ObjectRangeBounds, ObjectResult, ObjectStore, StreamingUploader,
};
use crate::object::{ObjectDataStream, ObjectMetadataIter};

#[derive(Error, Debug)]
pub enum Error {
    #[error("NotFound error: {0}")]
    NotFound(String),
    #[error("Other error: {0}")]
    Other(String),
}

impl Error {
    pub fn is_object_not_found_error(&self) -> bool {
        matches!(self, Error::NotFound(_))
    }
}

impl Error {
    fn not_found(msg: impl ToString) -> Self {
        Error::NotFound(msg.to_string())
    }

    fn other(msg: impl ToString) -> Self {
        Error::Other(msg.to_string())

View on GitHub (pinned to 6469eb736d)