diff --git a/frontend/src/metabase-lib/lib/queries/StructuredQuery.ts b/frontend/src/metabase-lib/lib/queries/StructuredQuery.ts
index 5d6150c139507739ca7bbe71a52a965802c3e8f8..045551ce3c6c5b7a3bcd7100afbebf2fd39e87de 100644
--- a/frontend/src/metabase-lib/lib/queries/StructuredQuery.ts
+++ b/frontend/src/metabase-lib/lib/queries/StructuredQuery.ts
@@ -212,7 +212,7 @@ export default class StructuredQuery extends AtomicQuery {
    * @returns the table ID, if a table is selected.
    */
   sourceTableId(): TableId | null | undefined {
-    return this.query()["source-table"];
+    return this.query()?.["source-table"];
   }
 
   /**
@@ -1437,7 +1437,7 @@ export default class StructuredQuery extends AtomicQuery {
    */
   @memoize
   sourceQuery(): StructuredQuery | null | undefined {
-    const sourceQuery = this.query()["source-query"];
+    const sourceQuery = this.query()?.["source-query"];
 
     if (sourceQuery) {
       return new NestedStructuredQuery(
diff --git a/frontend/test/metabase/scenarios/dashboard-filters/reproductions/20393-public-dashboard-nested-card-with-parameters.cy.spec.js b/frontend/test/metabase/scenarios/dashboard-filters/reproductions/20393-public-dashboard-nested-card-with-parameters.cy.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..196b8401bbca826b117d8ffc2e4eb36325f0c6a2
--- /dev/null
+++ b/frontend/test/metabase/scenarios/dashboard-filters/reproductions/20393-public-dashboard-nested-card-with-parameters.cy.spec.js
@@ -0,0 +1,71 @@
+import { restore, popover } from "__support__/e2e/cypress";
+
+describe("issue 20393", () => {
+  beforeEach(() => {
+    restore();
+    cy.signInAsAdmin();
+  });
+
+  it("should show public dashboards with nested cards mapped to parameters (metabase#20393)", () => {
+    createDashboardWithNestedCard();
+
+    // add a date parameter to the dashboard
+    cy.icon("pencil").click();
+    cy.icon("filter").click();
+    popover()
+      .contains("Time")
+      .click();
+    popover()
+      .contains("All Options")
+      .click();
+
+    // map the date parameter to the card
+    cy.get(".DashCard")
+      .contains("Select")
+      .click();
+    popover()
+      .contains("CREATED_AT")
+      .click();
+
+    // save the dashboard
+    cy.findByText("Save").click();
+
+    // open the sharing modal and enable sharing
+    cy.icon("share").click();
+    cy.findByText("Sharing and embedding").click();
+    cy.findByRole("switch").click();
+
+    // navigate to the public dashboard link
+    cy.findByText("Public link")
+      .parent()
+      .within(() => {
+        cy.get("input").then(input => {
+          cy.visit(input.val());
+        });
+      });
+
+    // verify that the card is visible on the page
+    cy.findByText("Q2");
+  });
+});
+
+function createDashboardWithNestedCard() {
+  cy.createNativeQuestion({
+    name: "Q1",
+    native: { query: 'SELECT * FROM "ORDERS"', "template-tags": {} },
+  }).then(({ body }) =>
+    cy
+      .createQuestion({
+        name: "Q2",
+        query: { "source-table": `card__${body.id}` },
+      })
+      .then(({ body: { id: cardId } }) =>
+        cy
+          .createDashboard("Q2 in a dashboard")
+          .then(({ body: { id: dashId } }) => {
+            cy.request("POST", `/api/dashboard/${dashId}/cards`, { cardId });
+            cy.visit(`/dashboard/${dashId}`);
+          }),
+      ),
+  );
+}