tonhowtf/omniget · error
invalid JSON
Error message
invalid JSON: {e} What it means
parse_json first deserializes the raw cookie-export content with serde_json::from_str; if the content is not syntactically valid JSON it wraps serde's error as 'invalid JSON: {e}'. This is the outermost gate before the array/object shape check and per-cookie parsing.
Solutions
- Validate the file is real JSON (e.g. JSON.parse in JS or jq . in shell) before importing.
- Export cookies in JSON format from the extension — do not pass cookies.txt / Netscape-format files to parse_json.
- Strip a UTF-8 BOM and any leading/trailing whitespace before parsing.
- Fix syntax errors named in the message (serde reports line/column) — trailing commas, unquoted keys, comments.
- If you need Netscape support, convert cookies.txt to JSON first or add a format-detecting wrapper.
Example fix
// before
let cookies = parsers::parse_json(&std::fs::read_to_string("cookies.txt")?)?; // Netscape text
// after
let content = std::fs::read_to_string("cookies.json")?;
let content = content.trim_start_matches('\u{feff}');
serde_json::from_str::<serde_json::Value>(content) // pre-validate
.map_err(|e| anyhow::anyhow!("cookie export is not valid JSON: {e}"))?;
let cookies = parsers::parse_json(content)?; Defensive patterns
Strategy: validation
Validate before calling
function validateCookieExport(text) {
const cleaned = text.replace(/^\uFEFF/, '').trim();
if (!cleaned.startsWith('[') && !cleaned.startsWith('{')) {
throw new Error('cookie export must be JSON (array or object), not cookies.txt');
}
JSON.parse(cleaned); // throws with position on syntax errors
return cleaned;
} Type guard
function isCookieJson(text) {
try { const v = JSON.parse(text); return Array.isArray(v) || (v && typeof v === 'object'); }
catch { return false; }
} Try / catch
try {
const cookies = await invoke('parse_cookies', { content: fileText });
} catch (e) {
if (String(e).startsWith('invalid JSON:')) {
showError('The selected file is not valid JSON. Export cookies as JSON, not cookies.txt.');
} else throw e;
} Prevention
- Only import JSON-format cookie exports, never Netscape cookies.txt
- Strip BOM and whitespace before parsing
- Hand edits to exports should be re-validated with a JSON linter
- Detect file format by sniffing the first character before calling parse_json
When it happens
Trigger: Calling parse_json (directly or via parse/parse_for_domain and the parse_json_* wrappers) with content that fails serde_json parsing: empty string, raw Netscape cookie-file text, JSON with trailing commas or comments, HTML error pages pasted instead of the export, BOM-prefixed or truncated files.
Common situations: User imports a cookies.txt (Netscape format) file instead of a JSON export; file truncated mid-transfer; editing the export by hand and breaking syntax; clipboard content with surrounding text or smart quotes; empty export from a fresh extension profile.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- No valid cookies found in file (expected Netscape format)
- Expected a JSON array of cookie objects.
- o servidor respondeu algo que não é JSON
- Failed to parse m3u8: neither master nor media playlist
- Unrecognized cookie format. Accepted: Netscape (yt-dlp)…
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/08d69fe9dce1d08a.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/src/cookies/parsers.rs:202
#[serde(default, alias = "httpOnly")]
http_only: Option<bool>,
#[serde(default)]
secure: Option<bool>,
#[serde(default, alias = "expirationDate", alias = "expires")]
expiration: Option<f64>,
name: String,
value: String,
#[serde(default, alias = "hostOnly")]
host_only: Option<bool>,
#[serde(default, alias = "sameSite")]
same_site: Option<String>,
#[serde(default)]
session: Option<bool>,
}
pub fn parse_json(content: &str) -> anyhow::Result<Vec<ExtensionCookie>> {
let raw: serde_json::Value =
serde_json::from_str(content).map_err(|e| anyhow::anyhow!("invalid JSON: {e}"))?;
let arr = match raw {
serde_json::Value::Array(a) => a,
serde_json::Value::Object(_) => vec![raw],
_ => anyhow::bail!("Expected a JSON array of cookie objects."),
};
let mut cookies = Vec::with_capacity(arr.len());
for item in arr {
let parsed: JsonCookie = match serde_json::from_value(item) {
Ok(c) => c,
Err(_) => continue,
};
let expires = match (parsed.session.unwrap_or(false), parsed.expiration) {
(true, _) => 0,
(false, Some(f)) => f as i64,
(false, None) => 0,
};
cookies.push(ExtensionCookie {
domain: parsed.domain,View on GitHub (pinned to 8600b91f42)