今日已更新 35 条资讯 | 累计 37284 条内容
关于我们

标签:#devchallenge

找到 284 篇相关文章

AI 资讯

The Counter That Counted a Call the Preflight Never Reached

This is a submission for DEV's Summer Bug Smash: Clear the Lineup , powered by Sentry . Project Overview I was working on a small Python component that performs a preflight check and then, if the check succeeds, invokes one synchronous operation callback. A counter records whether that callback invocation returned normally. The counter is used for diagnostics, so it must follow the control flow rather than the expected happy path. Bug Fix or Performance Improvement When a handled failure occurred, the old implementation still returned one: return 1 That value was hard-coded because the successful path was expected to invoke exactly one operation. If the preflight check failed, however, the operation was never entered and the function still returned one. An offline reproduction produced: operation_entries=0 old_count=1 The failure was handled, but the counter contradicted the actual control flow. Code Reduced to the relevant lines, the old behavior was: # Simplified pre-fix behavior def buggy_completed_calls ( * , preflight , operation ): try : preflight () operation () except Exception : pass return 1 Here is the complete fixed function from the standalone reproducer: from collections.abc import Callable Callback = Callable [[], None ] def completed_calls ( * , preflight : Callback , operation : Callback ) -> int : """ Return one only when the cooperative operation returned normally. """ try : preflight () operation () except Exception : return 0 return 1 The essential regression assertion is shown below. Both callbacks are local, so the test performs no network request: # Abbreviated test excerpt def test_preflight_failure_does_not_count_an_unentered_operation (): operation_entries = 0 def refuse_preflight (): raise RuntimeError ( " controlled preflight refusal " ) def operation (): nonlocal operation_entries operation_entries += 1 result = completed_calls ( preflight = refuse_preflight , operation = operation , ) assert operation_entries == 0 assert result == 0 My

2026-08-24 原文 →
AI 资讯

I wrote the privacy rule, enforced it, commented it, and shipped the leak anyway

This is a submission for DEV's Summer Bug Smash : Smash Stories. TL;DR. I wrote a scrubbing policy before writing any instrumentation code. I enforced it in a beforeSend hook. I unit tested it. I wrote a comment above the one obviously sensitive line saying exactly what it must never do. Then I intercepted the actual bytes leaving the browser and found a stranger's shoulder injury in them. Every guarantee I had written was about data my code hands to the SDK. None of them were about data the SDK collects on its own. The setup WhyRep is a workout tracker built local-first. Training data is created and read on the device, the tracker works offline with no account, and that is not a marketing line, it is the architecture. It is also the thing people decide to trust or not trust in about four seconds on the landing page. So when I added Sentry, the scrubbing policy came before the code. Written down, in the repo, as a list of things that may never appear in an event: exercise names, weights, reps, RIR, session notes, chat content. Never. On Android I enforced it twice. A beforeSend hook that strips the forbidden fields, and a unit test that constructs an event carrying each one and asserts it comes out stripped. @Test fun `beforeSend strips every field the policy forbids` () { val event = SentryEvent (). apply { setExtra ( "exerciseName" , "Incline Barbell Bench" ) setExtra ( "weightKg" , 82.5 ) setExtra ( "notes" , "left shoulder clicks past parallel" ) } val scrubbed = ScrubbingPolicy . scrub ( event , Hint ()) assertNull ( scrubbed ?. getExtra ( "exerciseName" )) assertNull ( scrubbed ?. getExtra ( "weightKg" )) assertNull ( scrubbed ?. getExtra ( "notes" )) } Green. Good. Then I wired up the landing site's share-link page. It decodes whyrep.com/t#<payload> , where the payload is somebody's entire workout template, base64 in the URL fragment. I was careful there too. On a decode failure it reports a coarse reason tag and never the payload: // NEVER send the payload i

2026-08-23 原文 →
AI 资讯

My performance optimization silently disabled the feature the app exists for

This is a submission for DEV's Summer Bug Smash : Smash Stories. TL;DR. I bounded a database read to make my analyzer faster. I derived the bound carefully, wrote the reasoning into the KDoc, and shipped it behind five passing tests. The bound was wrong in a way none of those tests could see. The result: if a lifter deloaded once in the middle of a stall, which is the correct thing for a lifter to do, my app stopped telling them they had plateaued. No crash. No error. No log line. The feature just quietly stopped being true for the people using the app correctly. The setup WhyRep analyzes your training rather than just recording it. The core promise is that it tells you when you have stalled and what to change about it, and that every verdict traces back to a methodology document rather than to something a language model made up. The architecture decision underneath that promise is that nothing is precomputed . Verdicts are derived from raw set logs on read, every time, so there is no cached judgement to go stale when the rules change. Which means every read walked the lifter's entire history for every exercise in the session. That is fine at ten sessions. It is not fine at three hundred. The obvious optimization is to bound the read. The obvious bound is "it only needs the last two weeks." That was my first wrong answer, and it is worth thirty seconds before I get to the interesting one. The plateau rules are not measured in calendar time. They are consecutive-miss counts, and the count varies by lifter tier and by whether the movement is a big or small joint action. The widest window in the signed methodology is an elite lifter on a small joint action: 14 consecutive sessions without progress. Train a lateral raise once a week and 14 sessions is over three months of data. A 14-day cutoff could never have fired a plateau for anyone above beginner tier. It would not have thrown. It would have quietly stopped detecting the exact thing the product exists to detect. Th

2026-08-23 原文 →
AI 资讯

Fixing a pgvector CI mismatch in a FastAPI RAG backend

This is a submission for DEV's Summer Bug Smash: Clear the Lineup , powered by Sentry . Project Overview mini-agent is a public FastAPI backend for an AI support-agent demo. Its test suite covers API behavior, authentication, rate limiting, approval flows, and PostgreSQL/pgvector-backed retrieval. The GitHub Actions workflow starts PostgreSQL and Redis service containers before running the Python test suite. The application database initialization also executes: CREATE EXTENSION IF NOT EXISTS vector The dependency is also visible in the DocumentChunk.embedding column, which uses pgvector's Vector type. That made the database image part of the test contract, not just incidental infrastructure. Bug Fix or Performance Improvement On August 12, 2026, the CI run for the preceding commit reached the test step and failed: Failed workflow run Commit tested by that run The workflow was using the general-purpose postgres:17-alpine service image, while the application required the pgvector extension during database initialization. The test environment therefore did not match the database capability required by the code. The failure was specific enough to avoid a broad rewrite: the container initialized successfully, dependency installation passed, and the workflow stopped only at Run tests . That pointed to the application/database boundary rather than the GitHub Actions runner or Python installation. The fix changed one line: services: postgres: - image: postgres:17-alpine + image: pgvector/pgvector:0.8.6-pg17 Full change: Use pgvector image in CI The PostgreSQL major version, credentials, port mapping, health check, application environment, dependency installation, and test command all remained unchanged. This kept the patch narrow and made the CI database expose the same required extension as the application. Code The evidence is a direct before-and-after pair: The preceding workflow failed at Run tests . The one-line database-image commit triggered a new workflow. The new

2026-08-22 原文 →
AI 资讯

The Bug That Hid Behind Its Own Comment: Fixing Inconsistent Inference in astroid

This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry . Project Overview astroid is the static-analysis engine that powers pylint — one of the most widely used linters in the Python ecosystem. Instead of running your code, astroid builds a model of what your code would do (a process called "inference") so pylint can catch real bugs before you ever hit run. That means astroid's inference logic has to be extremely consistent: if it gets confused about what a piece of code returns, pylint either misses real bugs, or — as in this case — flags perfectly correct code as broken. Bug Fix or Performance Improvement I picked up astroid issue #3077 : identical typing.cast(T, self) expressions were being inferred differently depending only on how the surrounding call was written — even when the code was structurally symmetric. In a class like this: class Base : def __call__ ( self ) -> str : return cast ( str , self ) def run ( self ) -> str : return cast ( str , self ) class IrJoin : separator : Base def __call__ ( self , items ): sep : str = self . separator () # implicit __call__ sugar return sep . join ( items ) def run ( self , items ): sep : str = self . separator . run () # explicit method call return sep . join ( items ) Both self.separator() and self.separator.run() do the exact same thing at runtime — I verified this by actually running the file. But pylint only flagged one of them: $ python -m pylint t5.py t5.py:35:15: E1101: Instance of 'Base' has no 'join' member (no-member) The explicit .run() path got a false positive; the equivalent implicit __call__ path did not, even though sep is a plain str in both cases at runtime. Code PR: https://github.com/pylint-dev/astroid/pull/3242 My Improvements Ruling out the obvious suspect My first hypothesis was infer_typing_cast , the function that handles typing.cast() itself — it seemed like the natural place for a cast-related inconsistency to live. Tested in isolation, though, it behaves identi

2026-08-22 原文 →
AI 资讯

The flaky test was right: a 58%-reproducible race in a scroll-reading pipeline's disk cache

This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry . Project Overview The Vesuvius Challenge uses machine learning to read carbonized Herculaneum scrolls, which is 2,000-year-old papyrus that got buried by the eruption of Vesuvius and can never be physically unrolled. Its open-source monorepo, ScrollPrize/villa, contains the vesuvius Python package that researchers use to stream multi-terabyte CT scan volumes and train ink-detection models. I was setting up that package on my Windows 11 machine (the project's CI only tests Ubuntu, and the workflow file literally says "Extend this list once the build scripts for macOS and Windows are confirmed"), working with an AI coding assistant to run the test suite on a platform it had never been tested on. One test failed. Then it passed. Then it failed again. Bug Fix or Performance Improvement The test, test_shared_cache_multiprocess_reads_are_not_torn, spawns four processes that read one scroll volume through a shared on-disk chunk cache. Run it once and you might not see anything wrong. So I ran it twelve times: 7 failures out of 12, all PermissionError: [WinError 5] Access is denied. A 58% flake isn't a flake. It's a bug with a coin flip attached. The cache is on the hot path for real usage. It's the component behind the package's documented volume_cache_dir config and the --cache-dir flag of its inference CLI. Any PyTorch DataLoader with num_workers > 0 puts multiple processes into exactly this concurrent pattern, so on Windows, training runs would randomly die mid-epoch. Once I dug in (a standalone reproducer that propagated full worker tracebacks instead of repr(exc)), the failure turned out to have three separate surfaces, each one hiding behind the previous one: Cache-entry commit. The zarr library commits each cache entry with a write-temp-then-os.replace pattern. On POSIX, rename(2) over a file another process has open is legal. On Windows, MoveFileEx(MOVEFILE_REPLACE_EXISTING) return

2026-08-22 原文 →
AI 资讯

Fixing a null-body crash in the Formbricks survey SDK, found by Sentry

This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry . A survey widget should not be able to take down the page it is embedded on. This one could: a single API response with a null body threw an uncaught TypeError in the visitor's browser. Sentry's bot found it, filed it as a GitHub issue, and Seer pointed at the exact line. Here is the fix. Project Overview Formbricks is an open-source survey and experience-management platform. Websites and apps embed a small JavaScript SDK that loads a survey, shows it to a user, and posts the answers back to the Formbricks API. The SDK lives in the monorepo as two packages: @formbricks/js-core (the loader and command queue) and @formbricks/surveys (the survey renderer). Both talk to the backend through a shared makeRequest helper. Bug Fix or Performance Improvement I fixed issue #6581 , a production crash that Sentry filed automatically: Bug: API data is not always validated in the surveys package TypeError: Cannot read properties of null (reading 'data') The issue was opened automatically by sentry[bot] , and its body carries the Sentry-captured (minified) stack trace plus a link to the source event, FORMBRICKS-CLOUD-3VE . Sentry did not just record this crash, it reported it. The SDK calls makeRequest to load a workspace's environment state. That code parsed the HTTP response and immediately read .data off the result: const json = ( await response . json ()) as ApiResponse ; // ... const successResponse = json as ApiSuccessResponse < T > ; return ok ( successResponse . data ); Two things go wrong here: response.json() on a body of literal null returns JavaScript null . Reading null.data throws TypeError: Cannot read properties of null (reading 'data') . The error path had the same problem one line up: errorResponse.code on a null body throws reading 'code' . response.json() is not guarded at all. A non-JSON body (an empty response, or an HTML error page from a proxy or CDN) makes it throw an unhan

2026-08-21 原文 →
AI 资讯

The Smallest Fix With The Biggest Impact [Skips VS Technology Edition]

This is a submission for DEV's Summer Bug Smash: Smash Stories powered by Sentry . Remember that one Regular Show episode where Skips tried to destroy the park's computer because it caught the Error 220 bug? He took one look at it, picked up a sledgehammer and said the line we’ve all felt as devs: “ There’s something evil in that computer. We gotta smash it ”. In the cartoon, they literally smash the computer and this works to fix the bug. In real life? We don’t get sledgehammers. We get Github PRs. Last week, I almost felt like Skips. I found a one-line bug in an open source repo that could’ve broken Instagram webhook security. No hammer, no explosion, just one misindented ‘if’ statement and a missing test. This is the story of how the smallest fix had the biggest impact. -The Challenge So what was my Error 220 ? While contributing to the corsair open-source repo, I found a security breach in the Instagram webhook handler. Something about the verification flow felt off, so I started tracing it line by line. The code called timingSafeEqual but the result was indecisive. I took an extensive look at it and that's when I saw it- The if statement meant to guard the check was there, but timingSafeEqual was indented wrong. It was meant to return the result of timingSafeEqual to accept or reject the request, but it fell through instead. Although it was running, its return value wasn’t being used to control the flow. This bug was tiny-one mis-indented line- but it had a great impact. In JS, it is not considered an error and so it’s easy to miss. Webhook security relies on a signature check to prove a request. If timingSafeEqual isn’t actually enforcing it, an attacker could forge a webhook and it would be accepted. The entire protection could fall apart over one tab. View PR #759 -The Fix In fixing it, I opened PR#759 to correct the indentation so crypto.timingSafeEqual would be inside the if block and its boolean result would decide whether to return true or false . Prior

2026-08-20 原文 →
AI 资讯

The Login Loop of Doom.

This is a submission for DEV's Summer Bug Smash: Smash Stories powered by Sentry . Code snippets are recreated and anonymized for illustrative purposes. The Symptom: A Revolving Door Instead of a Login Page It started innocently enough: I was clicking through our app and hit "Log in." Auth0's Universal Login page appeared, I entered my credentials, got redirected back to the app... and landed on the Auth0 login page again. And again. And again. No error message. No failed login attempt. Auth0 was happily authenticating me every single time — and our app was just as happily bouncing me right back, like a bouncer who checks your ID, nods, and then immediately forgets he checked it. The login loop. Every developer's favorite horror movie, now starring me. Red Herring #1: "It's the Frontend's Fault" My first suspect was the obvious one: the frontend callback handler. A Node.js/Express app sits in front of our Django API, handling the Auth0 redirect dance. A login loop screams "broken callback" or "state/nonce mismatch," so I spent a solid hour there: ✅ State parameter matched ✅ Nonce validated ✅ Callback URL whitelisted in the Auth0 dashboard ✅ ID token and access token both present in the response Everything the frontend touched was perfect. The tokens were real, signed by Auth0, freshly issued seconds ago. And yet the moment the frontend sent the access token to our Django API, the API answered with a flat 401 Unauthorized . Fine. New suspect. Red Herring #2: "Auth0 Must Be Misconfigured" Next stop: the Auth0 dashboard. Maybe the token lifetime was set to something absurd, like 5 seconds? Maybe the audience claim was wrong? Token lifetime: 3600 seconds. Normal. aud claim: matched our API identifier exactly. Signature: verified against the JWKS. Valid. So Auth0 was issuing perfectly good tokens, the frontend was delivering them intact, and Django was spitting them out. The bug had to be in the validation logic itself. Time to actually read the code we trusted blindly e

2026-08-19 原文 →
AI 资讯

# From Silent Failure to a Definitive Fix: Debugging an Existing AI Application

Clear the Lineup Submission The Bug AI applications can fail silently — producing wrong outputs, degraded performance, or unexpected behaviors without explicit errors. In my case, the issue was SQL drift: queries executed successfully but returned incomplete or unstable results due to unsafe wildcard usage (SELECT *). This silent failure propagated downstream, degrading model accuracy without obvious alerts. The Fix I introduced an agentic validation and inspection layer into the pipeline using LangGraph, StatesGraph, MCP, and A2A. Inspection Layer: Deterministic checks (SQL linters, schema validators). Validation Layer: Agentic reasoning about query safety. MCP Integration: Standardized access to profilers and monitoring APIs. A2A Collaboration: Agents exchanged context to enforce compliance. This combination allowed the system to detect unsafe queries and route them for human review before deployment. PR Link Here’s the merged PR where the fix was implemented: Continental-Thaligai Repository – Merged PRs https://github.com/NikhilRaman12/Continental-Thaligai/pulse#opened-pull-requests Code Snippet python from langgraph import Graph from statesgraph import State from mcp import MCPClient class SQLInspection(State): def run(self, query): if "SELECT" in query and "*" in query: return {"risk": 0.7, "message": "Wildcard SELECT may cause drift"} return {"risk": 0.1, "message": "Query safe"} graph = Graph() graph.add_state("sql_inspection", SQLInspection()) graph.connect("sql_inspection", "human_review", condition=lambda r: r["risk"] > 0.5) result = graph.run("SELECT * FROM transactions") print(result) Diff Example: diff SELECT * FROM transactions SELECT transaction_id, amount, date FROM transactions This change eliminated silent drift in query results and improved reliability in downstream AI pipelines. Outcome Silent SQL drift eliminated. Improved accuracy in downstream AI models. Added regression tests to prevent recurrence. Strengthened CI/CD pipeline with agentic saf

2026-08-19 原文 →
AI 资讯

Dog Whisperer

This is a submission for Weekend Challenge: Dog Days Edition Dog Whisperer is an app that looks at a photo of your dog, figures out what it's probably feeling, and then actually says it out loud in a voice that matches the mood. Grumpy dog gets a grumpy voice. Dramatically offended dog gets... a dramatically offended voice. You get the idea. It also doubles as a pet log — meals, weight, and walks tracked over time in Snowflake, with trend charts so you can actually see if your dog's been eating more than usual or losing weight. Add your pets and start logging. Use your unique username to keep track of your pets! Here is App in action: https://dogwhisperer-whi6rye8zklcdtnedyxmww.streamlit.app/ Demo Code Kaku-g / dog_whisperer How I Built It I used Google's Gemini (model: gemini-3.5-flash-lite ) to infer the mood of the dog (or cat, lizard, ferret — whoever's in the photo) from a single image, then passed that straight into Gemini's native TTS (model: gemini-3.1-flash-tts-preview ) to give it a voice that actually matches the mood — a sleepy dog sounds sleepy, a dramatic one sounds dramatic. For logging and trends, I used Snowflake — compute, databases, and tables — to store meals, weight, and walks for every pet and power the trend charts in the app. So it's really two things working hand in hand: a generative AI pipeline paired with a data warehouse. The AI part is what makes the app fun — inferring your pet's mood and giving it a voice. The Snowflake part is what gives it a real use case , since it's something you could keep using for long. Prize Categories I used Google AI and Snowflake, so I'm submitting under both: 🏆 Best Use of Google AI 🏆 Best Use of Snowflake

2026-08-17 原文 →
AI 资讯

Warm Hearth — A Landing Page Built Around One Fire

This is a submission for Frontend Challenge - Comfort Food Edition, Perfect Landing What I Built Warm Hearth — a landing page for a comfort food restaurant built around one idea: everything on the menu comes from the same wood-fired hearth in the back. Instead of treating "comfort food restaurant" as a generic brief, I anchored the whole page to that single hearth: An interactive hearth centerpiece. Right after the hero, there's a hand-drawn CSS/SVG fire pit you can click to "stoke." The flame flares, embers burst upward, and a small honest counter tracks how many times you've stoked it this visit — no fake global numbers, just a real, session-based response to your click. Four dishes, each with real cultural identity. Ramen, warm pies, a cheesy pasta bake, and gulab jamun — each with its own hand-drawn SVG illustration and a border motif pulled from its own cuisine (a jade-and-gold double line for the ramen, a scalloped pastry edge for the pies, an Italian tricolor accent for the pasta, gold paisley tones for the gulab jamun) rather than one generic card style stretched across all four. Living detail, not static photos. Steam rises off the ramen, pies, and pasta bake using the same wisp animation as the hero's hearth, so the whole page reads as one consistent "warmth" language. The gulab jamun gets a syrup shimmer and drip instead, since steam isn't the right detail for a syrup-soaked sweet. Price tags that hang like real kitchen tickets — pinned by a string, swaying gently, and giving a small "flicked" swing on hover instead of sitting flat on the card. Mira, an illustrated host in the corner who offers a rotating table tip when you click her — a small personal touch instead of a static "contact us" widget. Built for actual use, not just to look good in a screenshot: keyboard-focusable tab filters, a skip-to-content link, aria-live regions on the interactive parts, and full prefers-reduced-motion support that disables every animation without breaking the page. Dem

2026-08-17 原文 →
AI 资讯

I spent 11 days optimizing a search ranking that only I could see

This is a submission for DEV's Summer Bug Smash: Smash Stories powered by Sentry . The symptom: good numbers, no users I publish small automation tools on a marketplace. By August I had 23 of them live. Store search looked fine — measured repeatedly, from a real browser, against the real production endpoint: Search term My rank (store UI, Aug 2) sitemap checker #3 google play audit #1 Real numbers after 89 days: 1 active user across all 23 tools. $0 revenue. A #1 ranking and one user is not a rounding error. It is a contradiction, and I spent a week and a half resolving it in the wrong direction. Eleven days of correct answers to the wrong question If ranking is fine and users are zero, the fault must be downstream — that was the reasoning. So I went looking for it, carefully: Demand analysis. Pulled 3,655 listings, then went deeper to 12,834 to check for sampling bias in the first pass. (There was one. I found it and corrected it.) Naming analysis. Split the corpus by whether the title contained a well-known platform name. Median users: 5 vs 2. Age-cohort analysis. Measured the base rate for new listings: only 11% (n=9) get their first user within 0–3 days of publishing, against 74% at 14–30 days. Mine were young. The zeros were, statistically, unremarkable. Acted on all of it. Renamed 5 tools. Added output schemas across the board — the platform's own quality score went from 74 to 78–79. Every one of those produced a defensible number. Not one of them changed anything. That pattern is the actual signal, and I missed it for too long: when every hypothesis confirms and nothing moves, stop testing hypotheses and start testing the instrument. "It reproduced" is not "it's correct" I had re-measured the ranking several times over those days. Same answer each time. I read that as confirmation. It isn't. Re-running a measurement under identical conditions reproduces the same bias just as faithfully as it reproduces the same truth . Repetition rules out transient noise and

2026-08-17 原文 →
AI 资讯

My security hook silently stopped guarding. The bug was one line of encoding.

This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry . Project Overview I run a set of local policy guards around an AI coding agent. They are ordinary PreToolUse hooks: before the agent is allowed to perform an action, the proposed tool call is handed to a small Python script as JSON on stdin . The contract is two exit codes. exit 0 → allow exit 2 → block, and send the reason back to the agent as feedback There are several. One refuses access to credential paths. One intercepts destructive shell commands. One enforces a directory boundary. And one — malformed-read-guard.py — blocks the agent from reading files that contain corrupted tool-call syntax, because reading that syntax makes the model start emitting it too, and the session locks up. They had been working for weeks. One of them had also, for some of that time, been doing nothing at all. Bug Fix or Performance Improvement The symptom Same file. Same bytes. Two locations. Placed at an ASCII path → guard fires, exit 2 , read blocked. Placed under a directory whose name contains Japanese characters → exit 0 , read allowed. No exception. No stack trace. No log line. Nothing anywhere said a decision had been skipped. The hook ran, the hook returned "allow", and the agent read a file it was supposed to be protected from. The mechanism Three steps, and the ugly part is that each one is individually defensible. 1. The payload is UTF-8. The reader is not. Hook input is always UTF-8. But on Windows, Python opens sys.stdin using the locale encoding — on this machine, cp932 . So this line data = json . load ( sys . stdin ) decodes UTF-8 bytes as cp932. 2. Mojibake does not raise. That is the whole problem. cp932 is permissive enough that UTF-8 bytes map onto some sequence of characters. You do not get a UnicodeDecodeError you can catch and log. You get a string that is merely wrong, and it flows onward as valid data: 'C:\\...\\self-catering\\_\udc85部\\再開メモ.md' ← what the guard actually rec

2026-08-17 原文 →