astrid-runtime/astrid · error · InviteStoreError

(wrapped UTF-8 conversion error from invite store bytes)

Error message

(wrapped UTF-8 conversion error from invite store bytes)

What it means

The invite store file on disk is read as raw bytes and must be valid UTF-8 (TOML). If `str::from_utf8` fails, the underlying UTF-8 error is wrapped in an `io::Error` with `InvalidData` and rethrown as an `InviteStoreError::Io`.

Solutions

  1. Check the file encoding (`file` command) and convert it to UTF-8, or restore a known-good copy.
  2. Delete the corrupt store file so the store starts empty (pending invites will need re-issuing).
  3. Fix the tooling or editor that wrote non-UTF-8 content to the store.

Example fix

# before
iconv -f UTF-16 -t UTF-8 corrupt.toml > invites.toml  # wrong source encoding
# after
iconv -f UTF-16LE -t UTF-8 corrupt.toml > invites.toml && astrid invites list
Defensive patterns

Strategy: validation

Validate before calling

let bytes = std::fs::read(store_path)?;
if std::str::from_utf8(&bytes).is_err() {
    eprintln!("invite store is not valid UTF-8; restore or remove it");
    return Err(MyError::CorruptStore);
}

Type guard

fn is_utf8_file(p: &std::path::Path) -> bool {
    std::fs::read(p).map(|b| std::str::from_utf8(&b).is_ok()).unwrap_or(false)
}

Try / catch

match store.load() {
    Err(InviteStoreError::Io(e)) if e.kind() == std::io::ErrorKind::InvalidData => {
        warn!("corrupt/non-UTF-8 invite store, starting empty");
        InviteStore::empty()
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `load` → `load_from_disk` when the invite store file contains bytes that are not valid UTF-8 (binary content, wrong encoding, corruption).

Common situations: The store file was edited with a tool that saved UTF-16 or Latin-1; the file got corrupted or truncated mid-write; a binary file was copied over the store path.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/12b7f77503796a4c. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-kernel/src/invite/mod.rs:529

        {
            let _ = &self.path;
            return Ok(Vec::new());
        }
        #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
        {
            self.load_from_disk()
        }
    }

    #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
    fn load_from_disk(&self) -> Result<Vec<Invite>, InviteStoreError> {
        let bytes = match std::fs::read(&self.path) {
            Ok(b) => b,
            Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(Vec::new()),
            Err(e) => return Err(InviteStoreError::Io(e)),
        };
        let text = std::str::from_utf8(&bytes).map_err(|e| {
            InviteStoreError::Io(std::io::Error::new(std::io::ErrorKind::InvalidData, e))
        })?;
        if text.trim().is_empty() {
            if let Err(error) = self.save_to_disk(&[]) {
                warn!(
                    path = %self.path.display(),
                    %error,
                    "could not normalize empty invite store"
                );
            }
            return Ok(Vec::new());
        }
        let probe: SchemaProbe = toml::from_str(text).map_err(InviteStoreError::Toml)?;
        if probe.schema_version > STORE_SCHEMA_VERSION {
            return Err(InviteStoreError::Io(std::io::Error::new(
                std::io::ErrorKind::InvalidData,
                format!(
                    "invite store schema {} is newer than supported schema {STORE_SCHEMA_VERSION}",
                    probe.schema_version

View on GitHub (pinned to affd8760f4)