cube-js/cube · error

Live-preview token is invalid

Error message

Live-preview token is invalid

What it means

LivePreviewWatcher.setAuth decodes the middle segment of a JWT-style token (base64 JSON) to extract deploymentId and url. If JSON.parse or Buffer decoding fails — meaning the token is malformed, truncated, or not a JWT — it logs the internal exception and throws 'Live-preview token is invalid'.

Source

Thrown at packages/cubejs-backend-cloud/src/live-preview.ts:39

  private lastHash: string | undefined;

  private log(message: string) {
    console.log('☁️  Live-preview:', message);
  }

  public setAuth(token: string): AuthObject {
    try {
      const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
      this.auth = {
        auth: token,
        deploymentId: payload.deploymentId,
        url: payload.url,
      };

      return this.auth;
    } catch (e: any) {
      internalExceptions(e);
      throw new Error('Live-preview token is invalid');
    }
  }

  public startWatch(): void {
    if (!this.auth) {
      throw new Error('Auth isn\'t set');
    }

    if (!this.watcher) {
      this.log('Start with Cube Cloud');
      this.watcher = chokidar.watch(
        process.cwd(),
        {
          ignoreInitial: false,
          ignored: [
            '**/node_modules/**',
            '**/.*'
          ]

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Copy the full live-preview JWT from the Cube Cloud UI on one line, without quotes or trailing whitespace.
  2. Verify the token has the JWT form header.payload.signature and base64-decode the payload to confirm deploymentId/url are present.
  3. Set the token via the proper env var/config rather than manual paste to avoid truncation.
  4. Obtain a fresh live-preview token from Cube Cloud if the old one was revoked.

Example fix

// before
watcher.setAuth(process.env.CUBE_CLOUD_TOKEN ?? ''); // empty -> invalid
// after
const token = process.env.CUBE_LIVE_PREVIEW_TOKEN;
if (!token || token.split('.').length !== 3) throw new Error('CUBE_LIVE_PREVIEW_TOKEN must be a JWT');
watcher.setAuth(token);
Defensive patterns

Strategy: validation

Validate before calling

function looksLikeJwt(token: string | undefined): boolean {
  if (!token || token.split('.').length !== 3) return false;
  try {
    const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
    return !!payload.deploymentId && !!payload.url;
  } catch { return false; }
}
// usage: if (!looksLikeJwt(process.env.CUBE_LIVE_PREVIEW_TOKEN)) throw ...

Type guard

function isValidLivePreviewToken(t: unknown): t is string {
  return typeof t === 'string' && t.split('.').length === 3 && (() => { try { JSON.parse(Buffer.from(t.split('.')[1], 'base64').toString()); return true; } catch { return false; } })();
}

Try / catch

try {
  watcher.setAuth(token);
} catch (e) {
  if (e instanceof Error && e.message === 'Live-preview token is invalid') {
    // prompt user / fail startup with guidance on copying the full JWT
  } else throw e;
}

Prevention

When it happens

Trigger: Calling setAuth with a value that has no dot-separated base64 JSON payload: an empty string, an API key instead of a JWT, a truncated token, or a token copied with whitespace/quotes.

Common situations: Copy-pasting the wrong credential type (e.g. a deploy auth token instead of a live-preview JWT) into the live-preview token prompt; terminal wrapping breaking the token across lines; missing env var yielding an empty string.

Understand the failure class

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/7e98ed3a3efe950a. Report an issue: GitHub.