cube-js/cube · error
read_variables is not implemented for custom protocol: {:?}
Error message
read_variables is not implemented for custom protocol: {:?} What it means
ServerManager keeps session/database variables in a RwLock keyed by protocol. Only PostgreSQL has a variables store; when the connection uses a custom Extension protocol, read_variables panics because extension protocols have no variable storage.
Source
Thrown at rust/cubesql/cubesql/src/sql/server_manager.rs:80
pg_auth,
compiler_cache,
nonce,
config_obj,
configuration: ServerConfiguration::default(),
postgres_variables: RwLockSync::new(postgres_default_global_variables()),
}
}
pub fn read_variables(
&self,
protocol: DatabaseProtocol,
) -> RwLockReadGuard<'_, DatabaseVariables> {
match protocol {
DatabaseProtocol::PostgreSQL => self
.postgres_variables
.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: {:?}",
extView on GitHub (pinned to 7d981676b3)
Solutions
- Guard the call: only read variables when protocol is PostgreSQL; return empty variables for extensions
- Initialize a per-extension variables store in ServerManager for the extension protocol
- Route the variables request to the extension's own handler instead of server_manager.read_variables
- Patch server_manager.rs:80 to return a default empty DatabaseVariables for Extension
Example fix
// before
DatabaseProtocol::Extension(ext) => unimplemented!("read_variables is not implemented for custom protocol: {:?}", ext),
// after
DatabaseProtocol::Extension(_) => self.extension_variables.read().expect("failed to lock variables"), Defensive patterns
Strategy: type-guard
Validate before calling
fn supports_variables(protocol: &DatabaseProtocol) -> bool {
matches!(protocol, DatabaseProtocol::PostgreSQL)
}
if supports_variables(&session.protocol()) { vars = mgr.all_variables(...); } Type guard
fn is_postgres(p: &DatabaseProtocol) -> bool { matches!(p, DatabaseProtocol::PostgreSQL) } Try / catch
let vars = std::panic::catch_unwind(|| mgr.all_variables(protocol.clone()))
.map(|g| g.clone())
.unwrap_or_default(); // empty variables for extension protocols Prevention
- Check DatabaseProtocol before touching variable APIs
- Implement extension-protocol variable storage up front when adding a custom protocol
- Return empty/default variables for extensions instead of panicking
- Add protocol-coverage tests for all ServerManager methods
When it happens
Trigger: Calling all_variables (or anything that reads variables) on a session whose DatabaseProtocol is DatabaseProtocol::Extension(ext) — i.e. a custom/extension protocol connection that issues a SHOW or variables query.
Common situations: Implementing a custom CubeSQL extension protocol and a client sends SHOW/SET-style commands; protocol handlers that unconditionally query variables without checking protocol type first.
Related errors
- write_variables is not implemented for custom protocol: {:?}
- Does not work for standalone mode yet
- Unsupported grouping set type: {:?}
- Unsupported node type: {:?}
- Unable to convert List of {} to string
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/e24439b82edcaadd.
Report an issue: GitHub.