Stirling-Tools/Stirling-PDF · warning · Error

File is not valid JSON: ${(err as Error).message}

Error message

File is not valid JSON: ${(err as Error).message}

What it means

Thrown by parseAutomationFile when JSON.parse rejects the file text. The original SyntaxError is attached as cause. The file content is not valid JSON.

Source

Thrown at frontend/editor/src/core/utils/automationConverter.ts:394

  if (hasOperations && !hasPipeline) return "automate";
  return "unknown";
}

/**
 * Parse a JSON file's text content into a normalized AutomationConfig.
 * Auto-detects the format unless `expectedFormat` is supplied; throws with a
 * user-readable message on any structural problem.
 */
export function parseAutomationFile(
  fileText: string,
  toolRegistry: Partial<ToolRegistry>,
  expectedFormat?: "automate" | "folderScanning",
): ParsedAutomationImport {
  let raw: unknown;
  try {
    raw = JSON.parse(fileText);
  } catch (err) {
    throw new Error(`File is not valid JSON: ${(err as Error).message}`, {
      cause: err,
    });
  }

  const detected = detectAutomationFormat(raw);
  const format = expectedFormat ?? detected;

  if (expectedFormat && detected !== "unknown" && detected !== expectedFormat) {
    throw new Error(
      `Expected ${
        expectedFormat === "automate"
          ? "Automate JSON (operations array)"
          : "Folder Scanning JSON (pipeline array)"
      } but file looks like ${
        detected === "automate" ? "Automate JSON" : "Folder Scanning JSON"
      }.`,
    );
  }

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Confirm the file is genuinely JSON by opening it in a text editor.
  2. Strip a leading UTF-8 BOM before parsing.
  3. Validate with a JSON linter.
  4. Surface cause.message to the user for the parse position.

Example fix

// before
raw = JSON.parse(fileText);

// after
const clean = fileText.replace(/^\uFEFF/, '').trim();
if (!clean.startsWith('{') && !clean.startsWith('[')) {
  throw new Error('File does not look like JSON (unexpected first character).');
}
raw = JSON.parse(clean);
Defensive patterns

Strategy: try-catch

Validate before calling

const clean = fileText.replace(/^\uFEFF/, '').trim();
if (!clean.startsWith('{') && !clean.startsWith('[')) {
  throw new Error('Selected file is not JSON.');
}

Type guard

function looksLikeJson(text: string): boolean {
  const t = text.replace(/^\uFEFF/, '').trim();
  return t.startsWith('{') || t.startsWith('[');
}

Try / catch

try {
  return parseAutomationFile(text, toolRegistry, expectedFormat);
} catch (e) {
  if (e instanceof Error && /not valid JSON/i.test(e.message)) {
    throw new Error('The selected file is not valid JSON. Please choose an exported automation config.');
  }
  throw e;
}

Prevention

When it happens

Trigger: The file content is not parseable JSON: an HTML error/login page saved as .json, a truncated download, a UTF-8 BOM, binary, or CSV content.

Common situations: Downloaded an HTML error or login page instead of the config; user picked a non-JSON file; encoding/BOM issues; a truncated download.

Related errors


AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13). Data as JSON: /api/errors/98f6687929002cb9. Report an issue: GitHub.