{"record":{"id":"5ebf241277033530","repo":"facebook/flow","slug":"peeking-current-location-when-not-available","errorCode":null,"errorMessage":"Peeking current location when not available","messagePattern":"Peeking current location when not available","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_parser/src/parser_env.rs","lineNumber":1225,"sourceCode":"\n/// Answer questions about what comes next\npub(crate) mod peek {\n    use super::*;\n    use crate::token::TokenKind;\n\n    pub(crate) fn token<'a>(env: &'a mut ParserEnv) -> &'a TokenKind {\n        &env.lookahead_0().token_kind\n    }\n\n    pub(crate) fn loc<'a>(env: &'a mut ParserEnv) -> &'a Loc {\n        &env.lookahead_0().loc\n    }\n\n    /// loc_skip_lookahead is used to give a loc hint to optional tokens such as type annotations\n    pub(crate) fn loc_skip_lookahead(env: &ParserEnv) -> Loc {\n        let loc = env\n            .last_loc()\n            .expect(\"Peeking current location when not available\");\n        Loc {\n            start: loc.end,\n            ..loc.dupe()\n        }\n    }\n\n    pub(crate) fn errors(env: &mut ParserEnv) -> Vec<(Loc, ParseError)> {\n        let errors = env.lookahead_0().errors.as_errors();\n        if errors.is_empty() {\n            Vec::new()\n        } else {\n            errors.to_vec()\n        }\n    }\n\n    pub(crate) fn comments(env: &mut ParserEnv) -> Vec<Comment<Loc>> {\n        let consumed_comments_pos = env.consumed_comments_pos;\n        let comments = &env.lookahead_0().comments;","sourceCodeStart":1207,"sourceCodeEnd":1243,"githubUrl":"https://github.com/facebook/flow/blob/5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9/rust_port/crates/flow_parser/src/parser_env.rs#L1207-L1243","documentation":"loc_skip_lookahead (rust_port/crates/flow_parser/src/parser_env.rs:1211) synthesizes a zero-width loc hint at the end of the last consumed token by calling env.last_loc(), which returns None until the lexer has produced at least one result (last_lex_result is unset before the first token). The expect fires when the helper is consulted before any token has been consumed. It is an internal assertion: the parser is asking for a previous-token-end location when no previous token exists.","triggerScenarios":"Calling loc_skip_lookahead (directly or via a parse rule that requests a loc hint for an optional token such as a missing type annotation) while the parser is still at the very start of input: empty files, files whose first token is the construct being parsed, or an error-recovery path that resets state before the first token is lexed.","commonSituations":"Parsing empty or single-token files through entry points that eagerly compute loc hints; refactors that reordered lookahead/loc-hint calls in parse rules; unit tests with minimal snippets.","solutions":["Reproduce with the smallest input (often an empty string or one token) to confirm the at-start-of-input condition","Ensure the calling parse rule consumes or lookaheads at least one token before asking for a last_loc-derived hint","Prefer the lookahead-based loc (ParserEnv::lookahead_0().loc) when any token is available","If you maintain this code, fall back to a start-of-file Loc instead of expecting when last_loc() is None"],"exampleFix":"// before\nlet loc = env.last_loc().expect(\"Peeking current location when not available\");\n\n// after: fall back to a synthesized start-of-file loc\nlet loc = env.last_loc()\n    .map(|l| Loc { start: l.end, ..l.dupe() })\n    .unwrap_or_else(Loc::at_start); // empty loc at position 0","handlingStrategy":"type-guard","validationCode":"// Before asking for a loc hint derived from the previous token, ensure one exists\nif env.last_loc().is_none() {\n    // parser is at position 0: use a start-of-file loc, do not call loc_skip_lookahead\n    return start_loc_hint();\n}","typeGuard":"fn has_last_loc(env: &ParserEnv) -> bool {\n    env.last_loc().is_some()\n}","tryCatchPattern":"let loc = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| loc_skip_lookahead(env)))\n    .unwrap_or_else(|_| Loc::at_start()); // fall back to position 0","preventionTips":["In parse rules, consume or lookahead at least one token before requesting last_loc-derived hints","Add empty-file and single-token inputs to parser unit tests","Prefer lookahead_0().loc whenever any token is available"],"tags":["flow-parser","loc","assertion","start-of-input","lookahead"],"backgroundTag":"parser-position-unavailable","analyzedSha":"5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9","analyzedAt":"2026-08-20T10:41:37.992Z","contentChangedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}