Skip to main content
September 17, 2026
Solved

Repeated 404s from extensibility.lucid.app/application/properties/packageId

  • September 17, 2026
  • 2 replies
  • 12 views

 Hello Lucid Developer Support,

We're building Quodsi, a Lucidchart editor extension (package id 29e0d321-5cb2-4ae0-a1b6-dabd512c098c). While testing our package in local developer mode, we see a constant stream of failing requests from the Lucid editor itself. We also see OAuth sign-in behavior that we suspect is related. We'd appreciate help understanding both.

  Environment
  - Lucidchart in Chrome [version], Windows 11
  - Local test mode: npx lucid-package test-editor-extension, editor Developer menu → "Enter developer mode"
  - lucid-extension-sdk 1.1.3; lucid-package [version, from npx lucid-package --version]
  - The same package id is registered in the developer portal, where we upload dev/test builds
  - Extension scopes: READ, WRITE, DOWNLOAD, SHOW_MODAL, CUSTOM_UI, NETWORK, USER_INFO, OAUTH_TOKEN

  1. Repeated 404s

  With our extension loaded, the DevTools console fills with:

  GET https://extensibility.lucid.app/application/properties/29e0d321-5cb2-4ae0-a1b6-dabd512c098c 404 (Not Found)

  - In one session we saw about 1,200 of these errors.
  - Our extension code never calls this URL. We don't use getPackageSettings, setPackageSettings or showPackageSettingsModal. The only package-level API we use is lucid.getPackageId().
  - The requests appear to come from the Lucid editor itself, and keep repeating.
  - It happens with and without a second OAuth provider in our manifest (details below).
  - It does not happen until the developer/user opens the Quodsi right panel.
  - It happens with published zips installed as well.

  Questions:
  - What is application/properties/{packageId}, and what triggers it?
  - Is a 404 expected for a package running in local test mode, or does it mean something is misconfigured for our package, in the manifest or in the developer portal?
  - Is the request retried in a loop, and does it block or delay getOAuthToken, oauthXhr or performDataAction while it keeps failing?

  2. OAuth sign-in and data connector behaviour

  Our manifest declares a custom OAuth provider, and our data connector uses it:

  "oauthProviders": [
    {
      "name": "kinde",
      "title": "Quodsi Auth",
      "authorizationUrl": "https://<our-kinde-tenant>/oauth2/auth?prompt=login&audience=...",
      "tokenUrl": "https://<our-kinde-tenant>/oauth2/token",
      "revokeTokenUrl": "https://<our-kinde-tenant>/oauth2/revoke",
      "scopes": ["openid", "profile", "email"],
      "domainWhitelist": ["https://<our-kinde-tenant>"],
      "clientAuthentication": "clientParameters",
      "usePkce": true
    }
  ],
  "dataConnectors": [
    { "name": "quodsi_api_data_connector", "oauthProviderName": "kinde", "callbackBaseUrl": "..." }
  ]

  - "Sign in" does nothing: our "Sign in" button calls client.getOAuthToken('kinde'). Sometimes nothing visible happens and the promise doesn't resolve for a long time. Repeated clicks also do nothing. Later the user ends up signed in without doing anything further. After a page reload, a cached token takes about 4 seconds to come back from getOAuthToken('kinde').
  - Our workaround from Lucid support: earlier (2025), when our data connector used a provider named lucid (authorizationUrl: https://lucid.app/oauth2/authorize, tokenUrl: https://api.lucid.co/oauth2/token, scope offline_access), you advised calling this once before performDataAction would work:

  await client.oauthXhr("lucid", {
    url: "https://api.lucid.co/folders/search",
    headers: { "Lucid-Api-Version": "1", "Content-Type": "application/json" },
    data: "{}",
    method: "POST",
  });
  - Problems with that workaround: we moved the data connector to our own kinde provider in April 2026 but kept the workaround. It shows a separate "authorize Quodsi to use Lucidchart" consent dialog.
    - That dialog collides with other dialogs. We've seen DialogStackingError, a Sign-in click that does nothing, and a data action failing because the consent dialog couldn't open while one of our modals
      (showModal) was open.
    - Before the user signed in, running it in a local package also seemed to stop the Kinde sign-in prompt from appearing.
  - Test without it: we removed the workaround and the lucid provider in a test build. Data actions (performDataAction against our kinde connector) worked, and the 404s still appeared.

Questions:
  - With a data connector whose oauthProviderName is a custom provider (kinde), is the oauthXhr("lucid", …) workaround still required before performDataAction, or is it obsolete?
  - When getOAuthToken(provider) needs to prompt, can the prompt be blocked or delayed by another open dialog, or by the failing application/properties requests? Is there a recommended way to detect that and report it to the user, rather than waiting on a promise that doesn't resolve?
  - EditorClient.triggerAuthFlow(providerName) (returns { s: boolean }) has no description in the SDK reference. What is it for, and should an explicit "Sign in" button use it instead of getOAuthToken?
  - Is there a recommended order for user consent when a package has a custom provider for sign-in and data actions, so that the consent dialogs never collide?

  3. What we can provide
  - Full HAR or console export from a local test session
  - Our manifest (secrets removed)
  - A screen recording of the Sign-in click doing nothing and the 404 stream
  - Access to a dev/test build uploaded from the developer portal, if you'd like to reproduce on a non-local install

Thanks for your help. Please let us know what else would be useful.

Dan
Quodsi

Best answer by Pierce Bringhurst

  Hi Dan,

Thanks for the detailed report — it made this easy to run down. Grouped the way you asked.

1. The repeated 404s on application/properties/{packageId}

These are harmless — ignore them. That endpoint stores an internal app-classification flag, unrelated to getPackageSettings/package settings, and third-party packages (especially in local test mode) legitimately have no record, so a 404 is the expected response. Your extension never calls it — our client-side analytics layer does, once per interaction, and it currently doesn't cache the result, which is why you see it repeat as the panel gets busy. It's fire-and-forget on a path separate from getOAuthToken/oauthXhr/performDataAction, so it does not block, delay, or retry-loop any of those — it's just console noise. We're fixing the caching on our end; nothing needed from you. Filter application/properties in DevTools if you want a clean console meanwhile.

2. OAuth sign-in and the data connector

These are separate from the 404s and trace back to one thing: the leftover oauthXhr("lucid", …) workaround. You can remove it.
 

Is oauthXhr("lucid", …) still required before performDataAction?

No, it should be obsolete here. Your connector uses a custom provider (kinde), and performDataAction authorizes that provider on its own: if auth is needed the backend signals it and the editor opens the right dialog automatically. Keeping the old lucid prime-call forces an extra "authorize Quodsi to use Lucidchart" consent dialog you don't need — and that's the one colliding with your other dialogs.

Can the prompt be blocked/delayed by another open dialog?

Yes. DialogStackingError is what we log when a second dialog tries to open while one is already up — e.g. a consent dialog behind one of your showModal modals. When that happens the prompt can fail to present and getOAuthToken's promise sits unresolved, which matches "Sign in does nothing, then they're signed in later." So: never trigger sign-in while one of your modals is open, sequence dialogs so only one is live at a time, and drive the button off the promise with your own "waiting…" state + timeout rather than treating a slow resolve as a hang. (The ~4s after reload is just the cached-token server round-trip — expected.)

What is triggerAuthFlow(providerName) / { s }?

It's the lower-level "run the auth flow now" primitive that getOAuthToken calls internally when it needs to prompt; s is a success boolean (it doesn't return a token). For a Sign-in button, getOAuthToken('kinde') is the right call — the fix isn't which method you use, it's making sure no other dialog is open when it runs.
Recommended consent ordering: (1) drop the lucid provider and the oauthXhr("lucid", …) call; (2) do kinde sign-in as its own step with no other modal open; (3) let performDataAction trigger its own auth on demand; (4) never open a showModal modal and an auth dialog at the same time.
If sign-in still misbehaves after removing the lucid workaround, the most useful artifact is a HAR + console export from a "Sign in does nothing" moment, with the click timestamp — that tells us whether the auth dialog was suppressed by a collision or the token request stalled. 

Thanks, 
Pierce Bringhurst

Comments

Lucid product team
September 17, 2026

  Hi Dan,

Thanks for the detailed report — it made this easy to run down. Grouped the way you asked.

1. The repeated 404s on application/properties/{packageId}

These are harmless — ignore them. That endpoint stores an internal app-classification flag, unrelated to getPackageSettings/package settings, and third-party packages (especially in local test mode) legitimately have no record, so a 404 is the expected response. Your extension never calls it — our client-side analytics layer does, once per interaction, and it currently doesn't cache the result, which is why you see it repeat as the panel gets busy. It's fire-and-forget on a path separate from getOAuthToken/oauthXhr/performDataAction, so it does not block, delay, or retry-loop any of those — it's just console noise. We're fixing the caching on our end; nothing needed from you. Filter application/properties in DevTools if you want a clean console meanwhile.

2. OAuth sign-in and the data connector

These are separate from the 404s and trace back to one thing: the leftover oauthXhr("lucid", …) workaround. You can remove it.
 

Is oauthXhr("lucid", …) still required before performDataAction?

No, it should be obsolete here. Your connector uses a custom provider (kinde), and performDataAction authorizes that provider on its own: if auth is needed the backend signals it and the editor opens the right dialog automatically. Keeping the old lucid prime-call forces an extra "authorize Quodsi to use Lucidchart" consent dialog you don't need — and that's the one colliding with your other dialogs.

Can the prompt be blocked/delayed by another open dialog?

Yes. DialogStackingError is what we log when a second dialog tries to open while one is already up — e.g. a consent dialog behind one of your showModal modals. When that happens the prompt can fail to present and getOAuthToken's promise sits unresolved, which matches "Sign in does nothing, then they're signed in later." So: never trigger sign-in while one of your modals is open, sequence dialogs so only one is live at a time, and drive the button off the promise with your own "waiting…" state + timeout rather than treating a slow resolve as a hang. (The ~4s after reload is just the cached-token server round-trip — expected.)

What is triggerAuthFlow(providerName) / { s }?

It's the lower-level "run the auth flow now" primitive that getOAuthToken calls internally when it needs to prompt; s is a success boolean (it doesn't return a token). For a Sign-in button, getOAuthToken('kinde') is the right call — the fix isn't which method you use, it's making sure no other dialog is open when it runs.
Recommended consent ordering: (1) drop the lucid provider and the oauthXhr("lucid", …) call; (2) do kinde sign-in as its own step with no other modal open; (3) let performDataAction trigger its own auth on demand; (4) never open a showModal modal and an auth dialog at the same time.
If sign-in still misbehaves after removing the lucid workaround, the most useful artifact is a HAR + console export from a "Sign in does nothing" moment, with the click timestamp — that tells us whether the auth dialog was suppressed by a collision or the token request stalled. 

Thanks, 
Pierce Bringhurst

September 17, 2026

Thanks for the fast response!!