jlcodes99/cockpit-tools · error

messages.invalidJson

Error message

messages.invalidJson

What it means

resolveExternalImportBundleItems could not interpret the imported content as JSON at all: whole-content JSON.parse failed, the line-delimited fallback threw or produced nothing, and (for codex) the raw refresh-token fallback did not apply or returned nothing. messages.invalidJson is the terminal 'not parseable' error (line 385).

Source

Thrown at src/hooks/useProviderAccountsPage.ts:385

        return lineDelimitedItems;
      }
    } catch (error) {
      lineDelimitedError = error;
    }

    if (platformId === 'codex') {
      try {
        const rawRefreshTokenItems = parseCodexRawRefreshTokenItems(rawContent, messages);
        if (rawRefreshTokenItems && rawRefreshTokenItems.length > 0) {
          return rawRefreshTokenItems;
        }
      } catch (error) {
        throw error;
      }
    }

    if (lineDelimitedError) throw lineDelimitedError;
    throw new Error(messages.invalidJson);
  }

  if (parsed && typeof parsed === 'object' && 'code' in parsed) {
    const code = (parsed as { code?: unknown }).code;
    if (code !== 200 && code !== '200') {
      throw new Error(
        readBundleMessage((parsed as { msg?: unknown }).msg) ??
          readBundleMessage((parsed as { message?: unknown }).message) ??
          readBundleMessage((parsed as { error?: unknown }).error) ??
          messages.empty,
      );
    }
  }

  const root =
    parsed && typeof parsed === 'object' && 'data' in parsed
      ? (parsed as { data?: unknown }).data
      : parsed;

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Verify the content is valid JSON by running it through JSON.parse or a validator
  2. Re-export the bundle from the source tool instead of hand-copying
  3. Check the file/clipboard is not empty, truncated, or HTML
  4. For codex, supply lines each containing exactly one rt_... token if using raw format

Example fix

// before (not JSON)
accounts: [a, b]
// after
{"items":[{"refresh_token":"rt_a"},{"refresh_token":"rt_b"}]}
Defensive patterns

Strategy: validation

Validate before calling

if (!content || !content.trim()) throw new Error('Import content is empty');
try { JSON.parse(content); } catch { /* may still be raw token format for codex */ }

Type guard

const looksParseable = (content: string): boolean =>
  content.trim().startsWith('{') || content.trim().startsWith('[');

Try / catch

try {
  items = resolveExternalImportBundleItems(content, platformId, messages);
} catch (e) {
  if (e instanceof Error && e.message === messages.invalidJson) {
    showFormatHelp();
  }
}

Prevention

When it happens

Trigger: Content is neither valid JSON, nor >=2 lines of JSON objects, nor (for codex) token-bearing raw lines; also thrown for codex when the line-delimited parse failed with fewer than 2 lines and the raw fallback returned null (e.g. only whitespace).

Common situations: Uploading an empty or whitespace-only file; pasting HTML from a failed export page; binary/corrupted download; wrong clipboard content; a YAML/CSV export pasted into a JSON-only importer.

Related errors


AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05). Data as JSON: /api/errors/9c91d7bc0af8dad0. Report an issue: GitHub.