{"record":{"id":"196781d1f2dd9054","repo":"neon-bindings/neon","slug":"u32-overflow-ocurred-in-lifecycle-instanceid","errorCode":null,"errorMessage":"u32 overflow ocurred in Lifecycle InstanceId","messagePattern":"u32 overflow ocurred in Lifecycle InstanceId","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/neon/src/lifecycle.rs","lineNumber":43,"sourceCode":"    types::promise::NodeApiDeferred,\n};\n\n#[derive(Copy, Clone, Debug, Eq, PartialEq)]\n#[repr(transparent)]\n/// Uniquely identifies an instance of the module\n///\n/// _Note_: Since `InstanceData` is created lazily, the order of `id` may not\n/// reflect the order that instances were created.\npub(crate) struct InstanceId(u32);\n\nimpl InstanceId {\n    fn next() -> Self {\n        static NEXT_ID: AtomicU32 = AtomicU32::new(0);\n\n        let next = NEXT_ID.fetch_add(1, Ordering::SeqCst).checked_add(1);\n        match next {\n            Some(id) => Self(id),\n            None => panic!(\"u32 overflow ocurred in Lifecycle InstanceId\"),\n        }\n    }\n}\n\n/// `InstanceData` holds Neon data associated with a particular instance of a\n/// native module. If a module is loaded multiple times (e.g., worker threads), this\n/// data will be unique per instance.\npub(crate) struct InstanceData {\n    id: InstanceId,\n\n    /// Used to free `Root` in the same JavaScript environment that created it\n    ///\n    /// _Design Note_: An `Arc` ensures the `ThreadsafeFunction` outlives the unloading\n    /// of a module. Since it is unlikely that modules will be re-loaded frequently, this\n    /// could be replaced with a leaked `&'static ThreadsafeFunction<NapiRef>`. However,\n    /// given the cost of FFI, this optimization is omitted until the cost of an\n    /// `Arc` is demonstrated as significant.\n    drop_queue: Arc<ThreadsafeFunction<DropData>>,","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/neon-bindings/neon/blob/38960e4381d9ad13b551cdf2d261f609167c9bc2/crates/neon/src/lifecycle.rs#L25-L61","documentation":"Neon assigns every module instance a monotonically increasing `InstanceId` backed by a process-global `AtomicU32`. `next()` uses `checked_add` and panics if the counter would exceed `u32::MAX`. Reaching this requires billions of module-instance creations (e.g. many worker threads or repeated dlopen cycles) within one process, so the panic effectively signals runaway instance churn or counter corruption.","triggerScenarios":"Creating more than 2^32-1 Neon module instances in one process — typically a hot loop that spawns worker threads each loading the addon, or repeatedly loading/unloading the native module; also possible if instance data is re-initialized per call due to a bug.","commonSituations":"Thread-pool benchmarks or job systems that spawn a fresh Worker per task instead of reusing workers; test suites that load the addon in thousands of processes... or one process with per-test dynamic loads; a library embedding Neon that re-inits per request.","solutions":["Reuse worker threads / a fixed thread pool instead of creating a new Worker (and thus a new module instance) per task.","Load the addon once per process (module-level singleton) and share it across workers where possible.","Profile and fix any code path that triggers instance data initialization on every call; initialization should happen once per instance.","As a last resort, file/patch Neon to use u64 for the counter if your workload legitimately creates billions of instances."],"exampleFix":"// before\nfor job in jobs {\n    let w = Worker::new(); // new module instance per job\n    w.run(job);\n}\n\n// after\nlet pool = ThreadPool::new(8); // fixed workers, one module instance\nfor job in jobs { pool.run(job); }","handlingStrategy":"fallback","validationCode":"// keep a process-level counter of worker/module loads in JS\nlet loads = (global.__addonLoads = global.__addonLoads || 0) + 1;\nif (loads > 1e6) throw new Error('excessive addon instance churn');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reuse a worker pool instead of creating Workers per task","Load the addon once per process; avoid repeated dynamic load/unload","Monitor worker spawn rates in long-running services","Treat this panic as a symptom: fix the churn, don't catch it"],"tags":["rust","neon","overflow","workers"],"backgroundTag":"value-out-of-range","analyzedSha":"38960e4381d9ad13b551cdf2d261f609167c9bc2","analyzedAt":"2026-09-13T09:05:33.640Z","contentChangedAt":"2026-09-13T09:05:33.640Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}