cube-js/cube · error

write_variables is not implemented for custom protocol: {:?}

Error message

write_variables is not implemented for custom protocol: {:?}

What it means

The write-side counterpart of read_variables: SET-style updates to database variables are only implemented for PostgreSQL connections. For a custom Extension protocol, write_variables panics via unimplemented! instead of applying the change.

Source

Thrown at rust/cubesql/cubesql/src/sql/server_manager.rs:96

                .read()
                .expect("failed to unlock variables for reading"),
            DatabaseProtocol::Extension(ext) => unimplemented!(
                "read_variables is not implemented for custom protocol: {:?}",
                ext
            ),
        }
    }

    fn write_variables(
        &self,
        protocol: DatabaseProtocol,
    ) -> RwLockWriteGuard<'_, DatabaseVariables> {
        match protocol {
            DatabaseProtocol::PostgreSQL => self
                .postgres_variables
                .write()
                .expect("failed to unlock variables for reading"),
            DatabaseProtocol::Extension(ext) => unimplemented!(
                "write_variables is not implemented for custom protocol: {:?}",
                ext
            ),
        }
    }

    // TODO: Read without copy by holding acquired lock
    pub fn all_variables(&self, protocol: DatabaseProtocol) -> DatabaseVariables {
        self.read_variables(protocol).clone()
    }

    pub fn set_variables(&self, variables: DatabaseVariablesToUpdate, protocol: DatabaseProtocol) {
        let mut current = self.write_variables(protocol.clone());

        for new_var in variables.into_iter() {
            if let Some(current_var_value) = current.get(&new_var.name) {
                if !current_var_value.readonly {
                    current.insert(new_var.name.clone(), new_var);

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Skip variable writes for extension protocols (no-op or protocol-specific handling)
  2. Add a per-protocol variables map in ServerManager so extensions can store settings
  3. Handle SET commands inside the extension's own command handler before reaching server_manager
  4. Patch server_manager.rs:96 to persist extension variables like the Postgres path does

Example fix

// before
DatabaseProtocol::Extension(ext) => unimplemented!("write_variables is not implemented for custom protocol: {:?}", ext),
// after
DatabaseProtocol::Extension(_) => self.extension_variables.write().expect("failed to lock variables"),
Defensive patterns

Strategy: type-guard

Validate before calling

if matches!(protocol, DatabaseProtocol::PostgreSQL) { mgr.set_variables(...); } else { /* skip or route to extension */ }

Type guard

fn can_write_variables(p: &DatabaseProtocol) -> bool { matches!(p, DatabaseProtocol::PostgreSQL) }

Try / catch

let _ = std::panic::catch_unwind(|| mgr.set_variables(protocol.clone(), vars));
// treat extension protocols as variable-less sessions

Prevention

When it happens

Trigger: Calling set_variables on a session whose protocol is DatabaseProtocol::Extension(ext) — e.g. a client connected via a custom extension protocol issuing SET statements.

Common situations: Custom protocol clients sending SET / RESET commands; middleware that applies session variable changes without checking whether the protocol supports variable writes.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/473f009235e2e9a1. Report an issue: GitHub.