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
- Skip variable writes for extension protocols (no-op or protocol-specific handling)
- Add a per-protocol variables map in ServerManager so extensions can store settings
- Handle SET commands inside the extension's own command handler before reaching server_manager
- 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
- Gate SET handling on protocol type in the session loop
- Give extensions their own settings store so writes never reach the Postgres path
- Mirror all ServerManager methods across protocols with tests
- Log and no-op unsupported writes instead of unimplemented!
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
- read_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/473f009235e2e9a1.
Report an issue: GitHub.