ramensoftware/windhawk · warning

the mod source could not be parsed, so its settings were…

Error message

the mod source could not be parsed, so its settings were not exported

What it means

When exporting a mod, canonical_settings parses the mod's source code to extract its settings. If the source cannot be parsed, the settings cannot be canonically serialized, so a warning is recorded and the mod is exported without settings rather than failing the entire export.

Solutions

  1. Open the mod source and fix the syntax error that breaks parsing
  2. Restore the original mod source from the upstream repository or a backup
  3. Re-run the export; settings will be included once the source parses
  4. If settings are not needed, ignore the warning — the mod itself is still exported

Example fix

// before: broken mod source stored in user data
// ==WindhawkMod==
// @id example-mod
==/WindhawkMod==  (unterminated block)
// after: restore the complete metadata block
// ==WindhawkMod==
// @id example-mod
// ==/WindhawkMod==
Defensive patterns

Strategy: fallback

Validate before calling

// parse source before storing/exporting
match parse_mod_source(&src) {
    Ok(_) => proceed(),
    Err(e) => repair_source_or_warn(&e),
}

Prevention

When it happens

Trigger: export_mod -> canonical_settings receives mod source text that the parser rejects (syntax error, unsupported construct, or non-UTF8/garbled source).

Common situations: A user hand-edited the mod source and broke its syntax; a mod fetched from an incompatible Windhawk version; truncated or corrupted source stored in user data.

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.

Related errors


AI-assisted analysis of ramensoftware/windhawk@61d99ed8e1 (2026-09-12). Data as JSON: /api/errors/a1ee7f05d5cd84fa. Report an issue: GitHub.

Appendix: source

Thrown at src/windhawk-core/core/src/services/user_data.rs:318

            // of the whole section - cannot be seen half-done as an empty map.
            let raw = {
                let mod_lock = session.mod_lock(id);
                let _guard = mod_lock.read().unwrap_or_else(|e| e.into_inner());
                read_mod_settings(session, id)?
            };
            let settings = canonicalize_settings(&items, &raw);
            // An empty map (nothing stored, or every stored key stale and
            // dropped) carries nothing, so omit it rather than emitting an empty
            // `settings` object. `None` also makes `inspect` report the facet as
            // absent, consistent with the archive.
            if settings.as_object().is_some_and(Map::is_empty) {
                Ok(None)
            } else {
                Ok(Some(settings))
            }
        }
        Err(_) => {
            warnings.push(warn(
                id,
                "the mod source could not be parsed, so its settings were not exported",
            ));
            Ok(None)
        }
    }
}

/// Resolve the scope against the installed set, returning the storage ids to
/// export. An explicit id that is not installed is a selection error.
fn resolve_scope(
    scope: &ModScope,
    list: &ListInstalledModsResult,
) -> Result<BTreeSet<String>, CoreError> {
    match scope {
        ModScope::Keyword(ModScopeKeyword::All) => Ok(list.mods.keys().cloned().collect()),
        ModScope::Keyword(ModScopeKeyword::AllExceptLocal) => Ok(list
            .mods

View on GitHub (pinned to 61d99ed8e1)