Skip to content

Self-hosted dashboard fails at login with "Missing value for Stripe(): apiKey should be a string" #5344

Description

@mitc-gjuge

To Reproduce

  1. Run a self-hosted / development instance from canary (no NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY set — it isn't in apps/dokploy/.env.example).
  2. Log in.
  3. The dashboard fails to render.
Runtime IntegrationError
Missing value for Stripe(): apiKey should be a string.

Current vs. Expected behavior

Current: a self-hosted instance can't get past login. Setting NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY to any non-empty placeholder unblocks it, which is what identifies the cause.

Expected: a self-hosted instance never touches Stripe. IS_CLOUD / settings.isCloud is false, so nothing billing-related should be reachable.

What causes it

The import chain from the dashboard entry point is fully static:

apps/dokploy/pages/dashboard/home.tsx:13
  → components/dashboard/onboarding/onboarding-wizard.tsx:21
    → components/dashboard/onboarding/steps/plan-step.tsx:14

and plan-step.tsx calls Stripe at module scope, not inside the component:

const stripePromise = loadStripe(
  process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!,
);

The guard inside the wizard is a runtime one:

const { data: isCloud = true } = api.settings.isCloud.useQuery();
const visibleStepIds = isCloud ? ... : ...;

It decides which steps render. It cannot prevent the module from being imported, so loadStripe(undefined) runs on every self-hosted instance regardless. Stripe.js then throws IntegrationError because the key isn't a string.

components/dashboard/settings/billing/show-billing.tsx:45 does the same thing at module scope, and plan-step.tsx imports from it, so there are two paths to the same call.

Introduced by 2e2e0c8c2 ("feat: cloud onboarding wizard, billing trial card, and post-checkout server setup"). Server-side billing is unaffected — getBillingStatus returns early on !IS_CLOUD before creating a Stripe client. This is client-side only.

Possible fixes, in rough order of least invasive: move loadStripe inside the component (or a useMemo) so it only runs when the plan step actually renders; or lazy-load PlanStep behind the isCloud check; or make the call tolerant of a missing key.

Provide environment information

  • Dokploy v0.30.5 (canary at 1572008c)
  • Self-hosted, Docker, macOS host, Node 26, Next.js 16.3.0 (Turbopack)
  • NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY unset, as per .env.example

Which area(s) are affected? (Select all that apply)

Dashboard / UI

Are you deploying the applications where Dokploy is installed or on a remote server?

Dokploy Server

Additional context

Found while testing a DNS provider branch rebased on canary; it reproduces on plain canary and has nothing to do with that work. Worth flagging because it affects every self-hosted instance on this version, and the error message points at Stripe rather than at the onboarding wizard, which makes it easy to misattribute.

Will you send a PR to fix it?

No

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions