facebook/flow · error

failed to deserialize AST

Error message

failed to deserialize AST

What it means

Panics when bincode fails to decode the AST Program from already-decompressed bytes. The decoder relies on the thread-local DESERIALIZE_FILE_KEY (set internally just before) to resolve Loc offsets, and the encoding is tied to the exact serialized type layout. Failure therefore means corrupt data or a producer with a different schema/version.

Source

Thrown at rust_port/crates/flow_heap_serialization/src/lib.rs:53

    DESERIALIZE_FILE_KEY.with(|k| *k.borrow_mut() = Some(file_key.dupe()));
}

fn clear_file_key() {
    DESERIALIZE_FILE_KEY.with(|k| *k.borrow_mut() = None);
}

pub fn serialize_ast(ast: &Program<Loc, Loc>) -> Vec<u8> {
    let bytes = bincode::serde::encode_to_vec(ast, bincode::config::legacy())
        .expect("failed to serialize AST");
    compress(&bytes)
}

pub fn deserialize_ast(file_key: &FileKey, bytes: &[u8]) -> Arc<Program<Loc, Loc>> {
    let decompressed = decompress(bytes);
    set_file_key(file_key);
    let (ast, _): (Program<Loc, Loc>, _) =
        bincode::serde::decode_from_slice(&decompressed, bincode::config::legacy())
            .expect("failed to deserialize AST");
    clear_file_key();
    Arc::new(ast)
}

pub fn serialize_docblock(docblock: &Docblock) -> Vec<u8> {
    let bytes = bincode::serde::encode_to_vec(docblock, bincode::config::legacy())
        .expect("failed to serialize Docblock");
    compress(&bytes)
}

pub fn deserialize_docblock(file_key: &FileKey, bytes: &[u8]) -> Arc<Docblock> {
    let decompressed = decompress(bytes);
    set_file_key(file_key);
    let (docblock, _): (Docblock, _) =
        bincode::serde::decode_from_slice(&decompressed, bincode::config::legacy())
            .expect("failed to deserialize Docblock");
    clear_file_key();
    Arc::new(docblock)

View on GitHub (pinned to f88ac94bcf)

Solutions

  1. Invalidate the saved state/heap cache so ASTs are re-parsed from source
  2. Ensure the process that produced the bytes and the process consuming them run the same binary version
  3. Write state atomically (temp file + rename) to avoid truncated inputs

Example fix

// before
let ast = flow_heap_serialization::deserialize_ast(&file_key, &bytes);

// after — recover by re-parsing the source file
let ast = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    flow_heap_serialization::deserialize_ast(&file_key, &bytes)
})) {
    Ok(ast) => ast,
    Err(_) => {
        std::fs::remove_file(&cache_path).ok();
        let ast = parse_source_to_ast(&file_key)?;
        std::fs::write(&cache_path, flow_heap_serialization::serialize_ast(&ast)).ok();
        ast
    }
};
Defensive patterns

Strategy: fallback

Try / catch

match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    flow_heap_serialization::deserialize_ast(&file_key, &bytes)
})) {
    Ok(ast) => ast,
    Err(_) => { invalidate_and_reparse(&file_key, &cache_path)? }
}

Prevention

When it happens

Trigger: deserialize_ast on heap bytes written by a different flow binary version whose Program/Loc encoding changed; a file that decompresses but was truncated at a record boundary; a file whose recorded file_key differs structurally from what Loc decoding expects.

Common situations: Switching between flow builds/versions while reusing a saved state dir; partial writes from killed processes; test fixtures regenerated by an older toolchain.

Related errors


AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20). Data as JSON: /api/errors/1463d83caa571769. Report an issue: GitHub.