This is a submission for DEV's Summer Bug Smash: Smash Stories powered by Sentry.
"The best debugger is a well-rested mind armed with the right tools and a stubborn refusal to give up."
It started like any other day. I was browsing GitHub, coffee in hand, when I stumbled across a repository that made me . The issue tracker was filled with bug reports that all had something in common. They were being ignored. Not because the maintainers did not care, but because these bugs were hard. They were the kind of bugs that hide in race conditions, platform edge cases, and security blind spots. The kind that make you stare at the screen for hours before the answer finally clicks.
I am Aniruddha Adak, an AI Agent Engineer and Full-Stack Developer who builds autonomous systems. You can find my work on GitHub, read my blog at aniruddha-adak.vercel.app, or follow me on X and DEV.
Over the past several months, I went on a bug-smashing spree that resulted in 373 merged pull requests across the open source ecosystem. This is the story of the most chaotic, educational, and rewarding debugging journeys from that adventure.
cognee is an open source AI memory infrastructure project. Think of it as the long-term memory system for AI agents. It stores, retrieves, and connects knowledge across conversations. It is ambitious, complex, and used by developers who need their AI systems to remember things.
I was reviewing the API layer, tracing how settings were updated. The POST /api/v1/settings
endpoint caught my attention. It accepted a JSON payload and updated global configuration directly. No privilege check. No role verification. Just raw, unauthenticated power handed to anyone with a login token.
My stomach dropped.
In a production deployment, this meant any user could change LLM API keys, modify database connections, alter authentication settings, or disable security features entirely. This was not a subtle bug. This was a full system takeover waiting to happen.
I opened the codebase in the Antigravity agentic IDE and asked the AI to trace the authorization flow. Within seconds, it mapped the middleware stack and identified the gap. The settings route was registered without the admin guard that protected other sensitive endpoints.
I checked the test suite. There were tests for settings updates, but none tested authorization failure. The bug had been sitting there, invisible to the test suite, invisible to code review, invisible to everyone.
Closes #3084
This PR addresses the security vulnerabilities reported in #3084:
The fix was two lines of code. A decorator. require_superuser()
. That was it. Two lines that closed a security hole you could drive a truck through.
I also masked LLM credentials in the response payload so that even authorized users would not see sensitive API keys in settings read responses.
The simplest fixes are often the most important. This two-line change had more security impact than any complex feature I could have built. Always audit your authorization matrix. Always test the negative cases. Always assume that if a permission check is missing, someone will find it.
A user reported OS Error 3 on Windows when using local vector database storage. The error message was cryptic. The path looked fine. But LanceDB subprocesses were failing to open database files.
I fired up Antigravity and asked the AI to research Windows path handling. The answer came back immediately. Windows has a legacy maximum path length of 260 characters. When you exceed that, the API returns Error 3: The system cannot find the path specified. Even though the path exists.
The fix is to use the \\\\?\\
prefix, which enables extended-length paths up to 32,767 characters. But you cannot just slap that prefix on every path. It only works with absolute paths. It breaks relative paths. And it is Windows-only.
I traced the vector_db_url
through the cognee codebase. The path was being constructed in Python, passed to LanceDB, which then spawned a subprocess. The subprocess was where the failure occurred. The prefix needed to be added at the exact point where the path crossed from Python into the native layer.
I spun up a Windows VM and reproduced the bug. The path was only 180 characters, well under 260. But LanceDB was adding its own internal directory structure, pushing the effective path past the limit. The error was happening in code the user never saw.
Closes #2941
This PR automatically normalizes and prefixes absolute Windows paths for the vector_db_url when using local filesystem storage. This resolves OS Error 3 triggered by LanceDB subprocesses when generating long file paths for persisting vector data on Windows.
I implemented runtime platform detection. On Windows, the code now normalizes the path to absolute form and adds the extended-length prefix before passing it to LanceDB. On Linux and macOS, the path is passed through unchanged.
The key insight was that the fix had to be transparent. Users should not need to know about Windows path limits. The software should just work.
Cross-platform bugs are the hardest to find and the easiest to ignore. Most developers work on Linux or macOS. Windows users suffer in silence. When someone reports a Windows bug, treat it as a gift. They are telling you about a whole category of problems your development environment will never reveal.
The hold_lock
context manager in cognee was supposed to provide safe, concurrent access to shared resources. It was simple. Acquire a lock. Do some work. Release the lock. What could go wrong?
Error reports were coming in about unhandled exceptions during cleanup. The stack traces pointed to the lock release statement. But the lock was being acquired successfully. How could releasing it fail?
I studied the code. The pattern was:
lock = acquire_lock()
try:
yield lock
finally:
lock.release()
Looks fine, right? Wrong.
If acquire_lock()
failed and raised an exception, the finally
block would still execute. But lock
would be undefined or in an invalid state. The release would fail with its own exception, masking the original acquisition failure.
In high-concurrency environments, lock acquisition fails more often than you think. Timeouts, deadlocks, resource exhaustion. When that happens, the cleanup code makes things worse by throwing a second exception.
fixes #3294. This PR ensures that hold_lock only attempts to release the lock if it was successfully acquired. We now initialize the lock variable to None, attempt to acquire the lock inside the try block, and verify that the lock is not None in the finally block before calling release_lock.
I restructured the pattern:
lock = None
try:
lock = acquire_lock()
yield lock
finally:
if lock is not None:
lock.release()
Now the release only happens if the lock was actually acquired. The original exception propagates cleanly. No ghost exceptions haunting the cleanup.
Cleanup code needs the same scrutiny as main logic. We tend to focus on the happy path. But software spends most of its life on unhappy paths. The finally
block is where bugs go to breed. Never assume a resource was successfully acquired before trying to release it.
While contributing to openclaw, an agentic AI framework, I noticed something disturbing. The test suite had if (process.platform === 'win32') { return; }
scattered throughout. Entire categories of tests were being skipped on Windows.
I asked a simple question. Why?
The comments said "Windows does not support symlinks." But that has not been true since Windows Vista. Windows has supported symlinks since 2007. It requires specific permissions, and directory junctions work even without admin rights. The tests were skipping Windows based on a decade-old assumption.
This meant bugs in symlink handling, path resolution, and file operations were going completely undetected on the most common desktop operating system in the world.
Related: #90275
The output-directories.test.ts
test had a broad, unconditional skip for win32
platforms, meaning symlink rejection wasn't fully tested on Windows machines that do support symlinks/junctions. Additionally, the initial symlink capability probe was leaving uncleaned directories and failing linters.
To ensure that tests adapt dynamically to the environment's capabilities rather than blindly skipping based on OS. This makes the test suite more robust and accurate. The probe was updated to properly clean up after itself using fsSync.rmSync
in a finally block and correctly evaluate if directory symlinks can be created on the given system without polluting the temp directory.
No direct end-user impact. Improves test reliability and Windows developer experience by correctly evaluating symlink capabilities and ensuring no temporary directory pollution during testing.
Tests run and pass successfully. All linters (including oxlint) pass on the updated probe.
✓ extension-browser ../../extensions/browser/src/browser/output-directories.test.ts (2 tests) 270ms
Test Files 1 passed (1)
Tests 2 passed (2)
dir
symlinks elsewhere.No linked issue. This is a test portability improvement for existing install-path boundary coverage.
Standard_D4ads_v6
) through Crabbox.node scripts/run-vitest.mjs src/infra/install-safe-path.test.ts
cbx_be4230e2069c
, run run_0fb83e164185
:
RUN v4.1.8 C:/repo/openclaw
✓ infra src/infra/install-safe-path.test.ts (24 tests) 525ms
Test Files 1 passed (1)
Tests 24 passed (24)
main
uses it.runIf(process.platform !== "win32")
for all three cases.node scripts/run-vitest.mjs src/infra/install-safe-path.test.ts
node scripts/run-oxlint.mjs src/infra/install-safe-path.test.ts
tbx_01kv72nvfyz4fgpny8cyn48xfr
: pnpm check:changed
.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
skipIf
during test declaration.Replaces the hardcoded Windows skip in the QQ Bot file-utils test with a dynamic file-symlink capability check. If file symlinks are supported by the environment, the test executes. Otherwise, it skips gracefully while keeping coverage active on capable hosts.
The symlinked local-media helper test should reject symlinked media paths when the runtime can create file symlinks, but it should not fail the suite on Windows or restricted environments where file symlink creation is unavailable. Gating the test on actual capability avoids false negatives while preserving the security regression coverage where the behavior can be exercised.
extensions/qqbot/src/engine/utils/file-utils.test.ts
completed with 1 passed
test file, 4 passed
tests, and 1 skipped
symlink test when file symlink creation was unavailable.cb7d5a162e24f7ec5be6985e97b2b74ae45b20f9
changes the probe to async fs.promises
APIs and skips solely on !canCreateFileSymlinks
, which addresses the stale Copilot comments about non-Windows restricted environments and synchronous import-time filesystem work.Instead of skipping based on platform, I implemented dynamic capability checks. The tests now ask the operating system: "Can you create symlinks?" If yes, the test runs. If no, it skips with a clear explanation.
For directory operations, I used Windows junctions instead of symlinks. Junctions have been supported since Windows 2000 and do not require special privileges. For file symlinks, I check capability at runtime.
Assumptions are the root of all evil in software. Platform checks, version checks, feature detection. They all age poorly. Capability detection is the only approach that stays correct over time. Write code that asks what the system can do, not what you think it is.
opensre is a site reliability engineering platform that uses LLMs to classify alerts and identify root causes. The promise is powerful. Feed it your monitoring data, and it tells you what is wrong.
The synthetic QA tests were failing. The LLM was classifying healthy alerts as noise. Specifically, scheduled maintenance checks and healthy status pings with severity information and normal state were being marked is_noise=True
.
This was catastrophic. If the system filters out healthy signals as noise, it cannot establish a baseline. Without a baseline, every alert looks like an emergency. Engineers burn out. Pager fatigue sets in. Trust in the platform evaporates.
Using Antigravity with Google AI, I traced the classification pipeline. The problem was in the LLM extraction step. The prompt was not giving the model enough context to distinguish between "this alert is unimportant" and "this alert indicates a healthy state."
I needed to expand the training data. Specifically, the _build_database_directive()
function needed to learn about:
This PR fixes the 000-healthy
synthetic-qa failure (Fixes: #596).
is_noise=True
.is_clearly_healthy
function to loop infinitely because condition 4 requires at least one investigative operation.app/nodes/extract_alert/extract.py
prompt to explicitly state that informational states and health checks are NOT noise.app/nodes/plan_actions/build_prompt.py
to ensure the agent MUST still query relevant monitoring platforms for verification when it identifies informational or healthy states.app/nodes/plan_actions/node.py
to fall back and force at least one verification action if the LLM returns an empty plan to prevent infinite insufficient_evidence loops.app/nodes/root_cause_diagnosis/evidence_checker.py
to correctly evaluate via is not None
.pr_body.md
template.Resolves #598 and #599 by supplying the agent with specific database directives that inform the RCA logic of standard scenarios like Connection Exhaustion and Free Storage exhaustion.
_build_database_directive() has been expanded exponentially to train the AI to parse red herrings, distinguish between dual fault symptoms versus single root causes, infer missing Storage metrics organically, ignore healthy oscillating traffic metrics, and trace WAL replication lags adequately.
Resolves #606, resolves #607, resolves #608, resolves #609, resolves #610. Expands the _build_database_directive()
function to correctly train the LLM to identify Compositional Faults (treating simultaneous CPU and Storage constraints as independent sources while filtering out connection bounds), infer replication lag from bare WAL metrics despite missing Replica metrics, accurately ignore historical maintenance distractions via timestamps, identify stale autoscaling recovery, and distinguish VACUUM-driven Checkpoint Storms.
I delivered the fix in three batched PRs. Each batch expanded the directive system with new training scenarios. The LLM learned to recognize healthy patterns, distinguish them from noise, and handle complex edge cases.
The key was batching. One massive PR would have been impossible to review. Three focused PRs made each change tractable and reviewable.
AI systems are only as good as their training data. When your AI misclassifies, do not blame the model. Blame the data. And then fix it. The directive expansion approach I used here is applicable to any AI system that makes classification decisions.
In OpenMythos, a research tool for linear time-invariant systems, I encountered a numerical bug that broke a mathematical guarantee.
The spectral radius ρ(A)
must be less than 1 for system stability. The code computed it using exp(log_dt + log_A)
. After large gradient steps, log_dt + log_A
could drop below -20
. The exponential of -20
is approximately 2.06e-9
.
Here is the problem. Float32 machine epsilon is approximately 1.19e-7
. When you take the outer exponential of a number smaller than machine epsilon, the result rounds to exactly 1.0
. Not approximately 1.0
. Exactly 1.0
.
This broke the ρ(A) < 1
guarantee. The system appeared stable when it was not. In research code, this kind of silent failure can invalidate months of work.
After sufficiently large gradient steps, log_dt + log_A
can be driven below -20
, causing exp(-20) ≈ 2.06e-9
— smaller than float32 machine epsilon (≈ 1.19e-7
) — so the outer exp(-2.06e-9)
rounds to exactly 1.0
, silently invalidating the spectral radius stability guarantee.
LTIInjection.get_A()
-20
→ -14
At -14
: exp(-14) ≈ 8.3e-7
, which sits above the float32 ULP threshold at 1.0
(~5.96e-8
), ensuring exp(-exp(x))
is always representable as strictly less than 1.0
in float32.
return torch.exp(-torch.exp((self.log_dt + self.log_A).clamp(-20, 20)))
return torch.exp(-torch.exp((self.log_dt + self.log_A).clamp(-14, 20)))
The upper bound (20
) is unchanged; it guards against the opposite extreme (overflow → A ≈ 0
), which is not problematic for stability.
I implemented numerically stable computation using appropriate scaling and clamping. The fix prevents the intermediate result from falling below the representable range of float32.
Floating point arithmetic is a minefield. Every comparison, every exponentiation, every accumulation is a potential bug. When you are doing numerical computing, you need to think about precision at every step. The math might be correct on paper. The computer might still get it wrong.
I want to talk about the tools because they mattered enormously.
This is not a regular code editor. It is an AI-native development environment that understands context across your entire codebase. I used it for:
The AI models behind Antigravity, powered by Google, were the engine that made everything else possible. They helped me find bugs I would have missed, understand codebases faster, and implement fixes with confidence.
After 373 merged pull requests, here are the lessons that stuck:
Security first. The most impactful fixes are often the simplest. Two lines of authorization logic can prevent a system takeover.
Question assumptions. Windows does support symlinks. The lock was not always acquired. The path was not always short enough. Every assumption is a potential bug.
Batch complex work. Three small PRs are better than one massive PR. Reviewers stay engaged. Mistakes get caught. Progress is visible.
Clean up responsibly. The finally
block deserves the same attention as the try
block. Resource cleanup is where silent failures happen.
Train your AI right. When AI systems misclassify, fix the training data. The model is not broken. Its education is incomplete.
Precision matters. Floating point arithmetic will betray you if you let it guard. Think about numerical stability in every calculation.
| Metric | Count |
|---|---|
| Total merged pull requests | 373 |
| Repositories contributed to | 6+ |
| Security vulnerabilities patched | 2 |
| Cross-platform compatibility fixes | 5 |
| Race conditions resolved | 1 |
| AI classification accuracy improvements | 4 |
| Numerical stability fixes | 1 |
| Test coverage restorations | 3 |
| UI/UX fixes | 1 |
This journey has been one of the most rewarding experiences of my development career. Every bug I fixed made someone's software a little better. Every PR I merged taught me something new. Every community I joined welcomed my contributions.
Open source is not just about code. It is about showing up, doing the work, and making things better for everyone who comes after you.
To the maintainers who reviewed my PRs: thank you for your patience and your feedback.
To the users who reported the bugs: thank you for taking the time to write clear issue descriptions.
To DEV, Sentry, and Google AI: thank you for creating this challenge and for supporting the open source community.
I am Aniruddha Adak, and I am just getting started.