perspective-dev/perspective · error · Error
table_name not set in model
Error message
table_name not set in model
What it means
The anywidget render() function reads the `table_name` trait from the Jupyter model before establishing the Perspective client-server connection; a falsy (missing/empty) value means the Python side never set the trait, so no table can be opened. This is a fail-fast guard on required widget state.
Solutions
- Set the `table_name` attribute on the Python PerspectiveWidget before the frontend render (e.g. widget.table_name = "my_table")
- Verify the Python model's trait defaults include a valid table name for the binding_mode in use
- Log model.get("table_name") in the notebook to confirm what the kernel is sending
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at packages/anywidget/src/js/index.js:130 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of perspective-dev/perspective@11c8238c0c (2026-09-09).
Data as JSON: /api/errors/e89752bb1d9342ef.
Report an issue: GitHub.
Appendix: source
Thrown at packages/anywidget/src/js/index.js:130
},
() => {
model.send({ type: "hangup", client_id }, null);
},
);
const on_custom_msg = (msg, buffers) => {
if (msg.type === "binary_msg" && msg.client_id === client_id) {
const [dataview] = buffers;
psp_client.handle_response(dataview.buffer);
}
};
model.on("msg:custom", on_custom_msg);
model.send({ type: "connect", client_id }, null);
const binding_mode = model.get("binding_mode");
const table_name = model.get("table_name");
if (!table_name) {
throw new Error("table_name not set in model");
}
const table_promise = psp_client.open_table(table_name).then(async (t) => {
if (binding_mode === "client-server") {
const local_client = await perspective.worker();
const remote_view = await t.view();
return await local_client.table(remote_view);
} else if (binding_mode === "server") {
return t;
} else {
throw new Error(`unknown binding mode: ${binding_mode}`);
}
});
// The viewer's `load()` also accepts a `Client` (with `table` naming the
// binding in `ViewerConfig`) since the workspace->viewer merge, but the
// single-table widget loads a `Table` directly and treats `table_name` as
// the source of truth. The config's derived `table` field therefore has noView on GitHub (pinned to 11c8238c0c)