{"record":{"id":"5a6d2e9c81bf609f","repo":"loco-rs/loco","slug":"create-cleanup-runtime","errorCode":null,"errorMessage":"create cleanup runtime","messagePattern":"create cleanup runtime","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/testing/db.rs","lineNumber":142,"sourceCode":"            sqlx::query(AssertSqlSafe(query))\n                .execute(&pool)\n                .await\n                .expect(\"create DB schema\");\n        })\n    }\n\n    fn cleanup_db(&self) {\n        let connection_string = self.root_connection_string.clone();\n        let table_name = self.schema_name.clone();\n\n        // Run the drop on a dedicated OS thread with its own runtime (not\n        // `tokio::task::spawn_blocking`, which schedules onto the ambient\n        // runtime and cannot be awaited from a sync/Drop context) and `.join()`\n        // it so cleanup fully completes before `cleanup_db` returns. This is\n        // safe to call from `Drop::drop` since nothing here is `.await`ed on\n        // the caller's runtime.\n        std::thread::spawn(move || {\n            let rt = tokio::runtime::Runtime::new().expect(\"create cleanup runtime\");\n\n            rt.block_on(async {\n                let pool = Pool::<Postgres>::connect(&connection_string)\n                    .await\n                    .expect(\"db connection should success\");\n                let query = format!(\"drop database if exists {table_name};\");\n                sqlx::query(AssertSqlSafe(query))\n                    .execute(&pool)\n                    .await\n                    .expect(\"Drop database\");\n            });\n        })\n        .join()\n        .expect(\"db cleanup thread panicked\");\n    }\n}\n\npub struct SqliteTest {","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/loco-rs/loco/blob/23639d1e360dbc618073642b507d6f8664adbaff/src/testing/db.rs#L124-L160","documentation":"`cleanup_db` runs DB teardown from a synchronous context (including `Drop`) by spawning a dedicated OS thread that builds a fresh tokio `Runtime`. `Runtime::new()` failing — e.g. the process is out of resources or a runtime limitation is hit — panics with 'create cleanup runtime', aborting cleanup and typically surfacing during test teardown.","triggerScenarios":"Calling cleanup when the process cannot allocate a new tokio runtime (thread/resource exhaustion, `set_current_thread` runtime builder misconfiguration via env, extremely constrained containers).","commonSituations":"Huge parallel test suites hitting thread limits; container memory limits killing runtime bootstrap; exotic runtimes where tokio cannot spawn its blocking pool.","solutions":["Reduce test parallelism (`--test-threads`) or the number of concurrently live test DBs so fewer cleanup threads/runtimes exist","Raise container/thread limits (`ulimit -u`, more memory in CI)","Prefer explicit async cleanup (call teardown inside the test's runtime) over relying on sync Drop-based cleanup","Check tokio feature flags are the standard ones; do not globally disable rt features in dependency overrides"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Sanity-check headroom for spawning the cleanup runtime\nlet max_threads = std::fs::read_to_string(\"/proc/sys/kernel/threads-max\")\n    .ok().and_then(|s| s.trim().parse::<i64>().ok());\nprintln!(\"threads-max = {:?}\", max_threads); // low values risk Runtime::new failure","typeGuard":null,"tryCatchPattern":"// Prefer explicit async cleanup inside the test runtime over Drop-based sync cleanup\n// async test body:\n//   test_support.cleanup().await; // instead of relying on Drop\n","preventionTips":["Limit test parallelism when creating many test DBs","Do explicit async cleanup instead of relying on Drop","Give CI containers enough memory/thread limits","Keep tokio features standard (rt-multi-thread)"],"tags":["rust","tokio","testing","runtime","panic"],"backgroundTag":"internal-invariant-violation","analyzedSha":"23639d1e360dbc618073642b507d6f8664adbaff","analyzedAt":"2026-09-12T01:47:20.769Z","contentChangedAt":"2026-09-12T01:47:20.769Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}