dubinc/dub · error

Access token not found. Please run `dub login` to authentica

Error message

Access token not found. Please run `dub login` to authenticate with Dub.

What it means

getConfig reads the dub-cli config store (via Configstore); if it is empty, no access token has ever been saved by `dub login`. The CLI throws this to stop any authenticated API call before making a request without credentials. It means the local machine has no stored Dub credentials, not that a token is expired or invalid.

Source

Thrown at packages/cli/src/utils/config.ts:9

import type { DubConfig } from "@/types";
import { oauthClient } from "@/utils/oauth";
import Configstore from "configstore";

export async function getConfig(): Promise<DubConfig> {
  const configStore = new Configstore("dub-cli");

  if (!configStore.size) {
    throw new Error(
      "Access token not found. Please run `dub login` to authenticate with Dub.",
    );
  }

  const config = configStore.all as DubConfig;

  if (config.expires_at && Date.now() >= config.expires_at) {
    const { accessToken, refreshToken, expiresAt } =
      await oauthClient.refreshToken({
        accessToken: config.access_token,
        refreshToken: config.refresh_token,
        expiresAt: config.expires_at,
      });

    return await setConfig({
      access_token: accessToken,
      refresh_token: refreshToken,
      expires_at: expiresAt,

View on GitHub (pinned to f216b94a24)

Solutions

  1. Run `dub login` and paste an access token from app.dub.co to populate the config store.
  2. Verify the config file exists (Configstore stores it in ~/.config/configstore/dub-cli.json or platform equivalent) and is non-empty.
  3. In CI, create the config file as a setup step (echo JSON with accessToken into the configstore path) before running commands.
  4. Ensure the same OS user/HOME is used that originally ran `dub login`.

Example fix

// before
npx dub-cli link https://example.com  // Error: Access token not found...
// after
dub login   # paste token
npx dub-cli link https://example.com
Defensive patterns

Strategy: validation

Validate before calling

import { getConfig } from "@/utils/config";
// or check the file directly before invoking CLI commands
import fs from "fs";
import path from "path";
const cfgPath = path.join(process.env.XDG_CONFIG_HOME ?? path.join(process.env.HOME ?? "", ".config"), "configstore", "dub-cli.json");
const loggedIn = fs.existsSync(cfgPath) && fs.statSync(cfgPath).size > 0;
if (!loggedIn) throw new Error("Run `dub login` before running this command");

Type guard

function hasToken(config: unknown): config is { accessToken: string } {
  return typeof config === "object" && config !== null && "accessToken" in config && typeof (config as any).accessToken === "string" && (config as any).accessToken.length > 0;
}

Try / catch

try {
  const cfg = await getConfig();
  // use cfg
} catch (e) {
  if ((e as Error).message.includes("Access token not found")) {
    console.error("Not authenticated. Run `dub login` first.");
    process.exitCode = 1;
  } else throw e;
}

Prevention

When it happens

Trigger: Any CLI command that calls getConfig (e.g. `dub link`/shorten, `dub config`, `dub domains`) when the configstore file for 'dub-cli' is empty or missing (configStore.size is falsy).

Common situations: Fresh install of @dub/analytics-cli without running `dub login`; running the CLI in CI/containers or on a new machine where the home-dir config was never created; different user/HOME so the config file is not found.

Understand the failure class

Related errors


AI-assisted analysis of dubinc/dub@f216b94a24 (2026-08-31). Data as JSON: /api/errors/a4729e2670d16038. Report an issue: GitHub.