{"record":{"id":"0f5baf27cbf159a5","repo":"perspective-dev/perspective","slug":"perspectiveviewnotfoundexception","errorCode":null,"errorMessage":"PerspectiveViewNotFoundException","messagePattern":"PerspectiveViewNotFoundException","errorType":"exception","errorClass":"PerspectiveViewNotFoundException","httpStatus":null,"severity":"error","filePath":"rust/perspective-server/cpp/perspective/src/cpp/server.cpp","lineNumber":547,"sourceCode":"        if (!m_deleted_tables.contains(imap.first)) {\n            vec.push_back(imap.first);\n        }\n    }\n\n    return vec;\n}\n\nstd::shared_ptr<Table>\nServerResources::get_table_for_view(const t_id& view_id) {\n    PSP_READ_LOCK(m_write_lock);\n    return m_tables.at(m_view_to_table.at(view_id));\n}\n\nServerResources::t_id\nServerResources::get_table_id_for_view(const t_id& view_id) {\n    PSP_READ_LOCK(m_write_lock);\n    if (!m_view_to_table.contains(view_id)) {\n        throw PerspectiveViewNotFoundException();\n    }\n\n    return m_view_to_table.at(view_id);\n}\n\nstd::vector<ServerResources::t_id>\nServerResources::get_view_ids(const t_id& table_id) {\n    PSP_READ_LOCK(m_write_lock);\n    std::vector<t_id> out;\n    auto range = m_table_to_view.equal_range(table_id);\n    for (auto it = range.first; it != range.second; ++it) {\n        out.push_back(it->second);\n    }\n    return out;\n}\n\nbool\nServerResources::has_view(const t_id& id) {","sourceCodeStart":529,"sourceCodeEnd":565,"githubUrl":"https://github.com/perspective-dev/perspective/blob/11c8238c0c9c0b9e490b5a6a2dc277afad1e980a/rust/perspective-server/cpp/perspective/src/cpp/server.cpp#L529-L565","documentation":"`ServerResources::get_table_id_for_view` looks up which table a given view ID belongs to under a read lock; if the view ID is absent from the `m_view_to_table` map it throws `PerspectiveViewNotFoundException`. This means the client referenced a view the server no longer (or never did) track — typically because the view was deleted after a table was removed or the ID is stale/invalid.","triggerScenarios":"Calling a table-level operation (e.g. `table_from_view`, delete paths, or any handler that resolves a view back to its table) with a view ID that is not registered in `m_view_to_table` — after the owning table was deleted, after the view was already deleted, or with a fabricated/uninitialized ID.","commonSituations":"Client holds a reference to a `view()` whose table was deleted server-side; WebSocket session reconnected after server restart so old view IDs no longer exist; race where one code path deletes the table/view while another still uses the view handle.","solutions":["Keep the parent table alive as long as any of its views are in use; delete views before deleting tables","Wrap view operations in error handling that recreates the view (`table.view(...)`) when the server reports a missing view","Avoid reusing view handles across server restarts/reconnects — recreate table and view after reconnecting","Check for delete/race logic in your app that removes views or tables while other async work still references them"],"exampleFix":"// before\nconst view = table.view();\ntable.delete();\nawait view.to_json(); // PerspectiveViewNotFoundException\n// after\nconst view = table.view();\nawait view.to_json();\nview.delete();\ntable.delete();","handlingStrategy":"try-catch","validationCode":"// confirm the view handle is still usable before dependent ops\nif (!view || typeof view.table_id === \"undefined\") {\n  view = table.view(); // recreate\n}","typeGuard":null,"tryCatchPattern":"try {\n  await someOperationUsingView(view);\n} catch (e) {\n  if (String(e).includes(\"ViewNotFound\")) {\n    view = table.view(); // recreate the view and retry once\n  }\n}","preventionTips":["Delete views before deleting their parent tables","Never reuse view handles across server restarts/reconnects","Avoid concurrent delete + use of the same view from different async paths","Track view ownership in one place in your app"],"tags":["cpp","view-not-found","stale-reference","lifecycle"],"backgroundTag":"resource-not-found","analyzedSha":"11c8238c0c9c0b9e490b5a6a2dc277afad1e980a","analyzedAt":"2026-09-09T00:35:19.377Z","contentChangedAt":"2026-09-09T00:35:19.377Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}