cocoindex-io/cocoindex · critical

Environment::provide_key({}): {e}

Error message

Environment::provide_key({}): {e}

What it means

Environment::provide_key() stores a value under a named ContextKey; if the key is change-tracked, the provided value must be fingerprintable. When fingerprinting fails, the context provider returns an error and this method panics with the key name and reason. It indicates the value type cannot be hashed/fingerprinted for change detection.

Source

Thrown at rust/sdk/cocoindex/src/app.rs:173

                "Environment::provide: type `{}` has already been provided",
                std::any::type_name::<T>()
            );
        }
        self.state.insert(value);
        self
    }

    /// Inject a shared resource by named [`ContextKey`].
    ///
    /// Named keys are useful when multiple resources share the same Rust type
    /// and carry change-tracking.
    ///
    /// # Panics
    /// Panics if a change-tracked key cannot fingerprint the provided value.
    pub fn provide_key<T: Send + Sync + 'static>(mut self, key: &ContextKey<T>, value: T) -> Self {
        self.context
            .provide(key, value)
            .unwrap_or_else(|e| panic!("Environment::provide_key({}): {e}", key.name()));
        self
    }

    /// Build the environment, opening (or creating) the LMDB database.
    ///
    /// # Errors
    ///
    /// Returns an error if the LMDB database environment fails to initialize
    /// (e.g., due to permissions, disk space, or a corrupted state directory).
    pub async fn build(self) -> Result<Environment> {
        // Register every `#[coco::function]`'s logic fingerprint into the engine's
        // logic set, so memo entries that depend on them validate correctly
        // (see `crate::logic`). Idempotent across builds.
        crate::logic::register_all_fn_logic();

        let db_path = self
            .db_path
            .unwrap_or_else(|| PathBuf::from("./coco_state"));

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Implement the fingerprint trait for the value's type (or derive it if available).
  2. Provide a fingerprintable projection instead (e.g. a connection-string String rather than the pool object).
  3. Use plain provide() with a unique type if change tracking is not needed for this value.
  4. Read the appended `{e}` message for the exact type that failed to fingerprint.

Example fix

// before
provide_key(&APP_CFG_KEY, cfg) // cfg not fingerprintable

// after
#[derive(Fingerprint)]
struct AppConfig { dsn: String }
provide_key(&APP_CFG_KEY, AppConfig { dsn: cfg.dsn })
Defensive patterns

Strategy: validation

Validate before calling

// ensure the value type implements the fingerprint trait before providing
fn assert_fingerprintable<T: cocoindex::Fingerprint>(_v: &T) {}
assert_fingerprintable(&value);

Prevention

When it happens

Trigger: Calling builder.provide_key(&KEY, value) where KEY is a change-tracked ContextKey whose value type does not implement the fingerprinting trait, or whose fingerprint computation errors (e.g. contains an unfingerprintable nested type).

Common situations: Defining a custom ContextKey over a struct without implementing the required fingerprint trait; upgrading cocoindex and a previously fingerprintable type losing its impl; passing a closure or handle type that cannot be hashed.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/a78d51d2765fb6e6. Report an issue: GitHub.