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

  1. Set the `table_name` attribute on the Python PerspectiveWidget before the frontend render (e.g. widget.table_name = "my_table")
  2. Verify the Python model's trait defaults include a valid table name for the binding_mode in use
  3. 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 no

View on GitHub (pinned to 11c8238c0c)