pyrefly icon indicating copy to clipboard operation
pyrefly copied to clipboard

Language Server Panic Crash on Startup in Remote Container in VSCode

Open MuehlASP opened this issue 1 month ago • 2 comments

Describe the Bug

When I use VSCode to connect to a remote dev Container, pyrefly loads up and then almost immediately crashes.

This is the case for around 80% of the startups. I currently "fix" it by restarting until the Language Server does not crash, which then leads to a stable environment.

This is the startup configuration: ( blanked project information )

pyreflylogs.txt

The codebase is not public, so i cant share anything apart from some traces from the extension log:

ERROR Thread panicked, shutting down: panicked at pyrefly/lib/state/state.rs:1559:17: assertion failed: inserted Backtrace: 0: std::sync::poison::once::Once::call_once::{{closure}} 1: std::sys::sync::once::futex::Once::call 2: pyrefly_util::panic::print_panic 3: pyrefly_util::panic::exit_on_panic::{{closure}} 4: std::panicking::rust_panic_with_hook 5: std::panicking::begin_panic_handler::{{closure}} 6: std::sys::backtrace::__rust_end_short_backtrace 7: __rustc::rust_begin_unwind 8: core::panicking::panic_fmt 9: core::panicking::panic 10: pyrefly::state::state::TransactionHandle::get_module 11: <pyrefly::state::state::TransactionHandle as pyrefly::export::exports::LookupExport>::get 12: pyrefly::binding::stmt::<impl pyrefly::binding::bindings::BindingsBuilder>::stmt 13: pyrefly::state::steps::Step::step_answers 14: core::ops::function::FnOnce::call_once{{vtable.shim}} 15: pyrefly::state::state::Transaction::demand 16: pyrefly::state::state::Transaction::lookup_answer 17: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_from_module 18: pyrefly::alt::attr::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::lookup_attr_from_attribute_base1 19: pyrefly::alt::attr::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::lookup_attr_from_attribute_base 20: pyrefly::alt::attr::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::type_of_attr_get 21: pyrefly::alt::expr::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::attr_infer 22: pyrefly::alt::expr::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::expr_infer_type_info_with_hint 23: pyrefly::alt::expr::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::expr_infer_type_no_trace 24: pyrefly::alt::expr::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::expr_infer_type_info_with_hint 25: pyrefly::alt::expr::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::expr 26: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type 27: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type_info 28: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::solve_binding 29: pyrefly::alt::answers_solver::AnswersSolver<Ans>::calculate_and_record_answer 30: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_idx 31: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type 32: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type_info 33: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::solve_binding 34: pyrefly::alt::answers_solver::AnswersSolver<Ans>::calculate_and_record_answer 35: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_idx 36: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type_info 37: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::solve_binding 38: pyrefly::alt::answers_solver::AnswersSolver<Ans>::calculate_and_record_answer 39: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_idx 40: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type_info 41: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::solve_binding 42: pyrefly::alt::answers_solver::AnswersSolver<Ans>::calculate_and_record_answer 43: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_idx 44: pyrefly::alt::answers_solver::AnswersSolver<Ans>::calculate_and_record_answer 45: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_idx 46: pyrefly::alt::expr::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::expr_infer_type_info_with_hint 47: pyrefly::alt::expr::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::expr 48: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type 49: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type_info 50: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::solve_binding 51: pyrefly::alt::answers_solver::AnswersSolver<Ans>::calculate_and_record_answer 52: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_idx 53: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter 54: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type 55: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type_info 56: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::solve_binding 57: pyrefly::alt::answers_solver::AnswersSolver<Ans>::calculate_and_record_answer 58: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_idx 59: pyrefly::alt::answers_solver::AnswersSolver<Ans>::calculate_and_record_answer 60: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_idx 61: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type 62: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type_info 63: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::solve_binding 64: pyrefly::alt::answers_solver::AnswersSolver<Ans>::calculate_and_record_answer 65: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_idx 66: pyrefly::alt::class::class_field::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::analyze_class_field_value 67: pyrefly::alt::answers_solver::AnswersSolver<Ans>::calculate_and_record_answer 68: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_idx 69: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_from_module 70: pyrefly::alt::class::class_field::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::get_non_synthesized_field_from_current_class_only 71: pyrefly::alt::class::class_field::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::get_class_member 72: pyrefly::alt::class::class_field::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::instance_as_dunder_call 73: pyrefly::alt::call::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::as_call_target_impl 74: pyrefly::alt::call::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::as_call_target_or_error 75: pyrefly::alt::answers_solver::AnswersSolver<Ans>::calculate_and_record_answer 76: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_idx 77: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type 78: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::binding_to_type_info 79: pyrefly::alt::solve::<impl pyrefly::alt::answers_solver::AnswersSolver<Ans>>::solve_binding 80: pyrefly::alt::answers_solver::AnswersSolver<Ans>::calculate_and_record_answer 81: pyrefly::alt::answers_solver::AnswersSolver<Ans>::get_idx 82: pyrefly::alt::answers::Answers::solve 83: pyrefly::state::steps::Step::step_solutions 84: core::ops::function::FnOnce::call_once{{vtable.shim}} 85: pyrefly::state::state::Transaction::demand 86: pyrefly::state::state::Transaction::run_step::{{closure}} 87: <rayon_core::job::HeapJob<BODY> as rayon_core::job::Job>::execute 88: rayon_core::registry::WorkerThread::wait_until_cold 89: rayon_core::scope::scope::{{closure}} 90: <rayon_core::job::StackJob<L,F,R> as rayon_core::job::Job>::execute 91: rayon_core::registry::WorkerThread::wait_until_cold 92: std::sys::backtrace::__rust_begin_short_backtrace 93: core::ops::function::FnOnce::call_once{{vtable.shim}} 94: std::sys::pal::unix::thread::Thread::new::thread_start`

The logs then show some more responses and end in:

[Error - 8:24:31 AM] Client Pyrefly language server: connection to server is erroring. write EPIPE Shutting down server. [Trace - 8:24:31 AM] Sending request 'shutdown - (17)'. [Error - 8:24:31 AM] Client Pyrefly language server: connection to server is erroring. write EPIPE [Error - 8:24:31 AM] Connection to server got closed. Server will not be restarted. [Error - 8:24:31 AM] Server process exited with code 101. [Error - 8:24:31 AM] Stopping server failed Message: Cannot call write after a stream was destroyed Code: -32099 [Error - 8:24:31 AM] Stopping server failed Message: Cannot call write after a stream was destroyed Code: -32099

Sandbox Link

No response

(Only applicable for extension issues) IDE Information

VSCode version 1.106.2, Extension version 0.43.1

Workspace spanning 2 repositories,

MuehlASP avatar Dec 01 '25 07:12 MuehlASP

From a bit of poking, the crash appears to be in the get_module rdeps insertion check:

    fn get_module(
        &self,
        module: ModuleName,
        path: Option<&ModulePath>,
    ) -> FindingOrError<ArcId<ModuleDataMut>> {
        let require = self.module_data.state.read().require;
        if let Some(res) = self.module_data.deps.read().get(&module).map(|x| x.first())
            && path.is_none_or(|path| path == res.path())
        {
            return FindingOrError::new_finding(self.transaction.get_imported_module(res, require));
        }

        let handle = self
            .transaction
            .import_handle(&self.module_data.handle, module, path);
        handle.map(|handle| {
            let res = self.transaction.get_imported_module(&handle, require);
            let mut write = self.module_data.deps.write();
            let did_insert = match write.entry(module) {
                Entry::Vacant(e) => {
                    e.insert(SmallSet1::new(handle));
                    true
                }
                Entry::Occupied(mut e) => e.get_mut().insert(handle),
            };
            if did_insert {
                let inserted = res.rdeps.lock().insert(self.module_data.handle.dupe()); 
                assert!(inserted);     /* <-------  panic seems to be coming from here  */
            }
            // Make sure we hold the deps write lock until after we insert into rdeps.
            drop(write);
            res
        })
    }

stroxler avatar Dec 01 '25 17:12 stroxler

See also https://github.com/facebook/pyrefly/issues/1424

I have been investigating a bug that crashes at the same place, and have a change up for review internally to fix it. Would appreciate if you could try out the fix when it's ready. Will keep you posted.

samwgoldman avatar Dec 02 '25 00:12 samwgoldman

This issue has someone assigned, but has not had recent activity for more than 2 weeks.

If you are still working on this issue, please add a comment so everyone knows. Otherwise, please unassign yourself and allow someone else to take over.

Thank you for your contributions!

github-actions[bot] avatar Dec 17 '25 00:12 github-actions[bot]