frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

fp.

Open in hackernews

A subtle bug with Go's errgroup

https://gaultier.github.io/blog/subtle_bug_with_go_errgroup.html
27•broken_broken_•6mo ago

Comments

nasretdinov•6mo ago
So it's really the issue due a partial variable shadowing during assignment, not errgroup-specific. Got bitten by it multiple times unfortunately, but I don't think there's an easy lint or vet check that could prevent such errors from happening. Having said that, overwriting a variable during := assignment is typically only useful for errors, so potentially you might want to have a lint check that complains when you've overwritten something else. There's already a check that the value is unused so when re-assigning the error value you're less likely to miss anything
yubblegum•6mo ago
> So it's really the issue due a partial variable shadowing during assignment, not errgroup-specific.

Did we read the same article? The "alternative fix" is to paper over documented bahavior of a context. Of course it makes sense that if wait returns context should be canceled. The one character fix is throwing away information ..

masklinn•6mo ago
> The one character fix is throwing away information ..

It's duplicate information, since Wait essentially provides the same thing (and in fact the context returned is mostly to solely for the callbacks to use, if the callbacks don't need it, it should be thrown away).

dondraper36•6mo ago
That's why I often use eg, egCtx :)
eddythompson80•6mo ago
No? Its about errgroup ctx being automatically cancelled once the group is done (in success or err). It kinda makes sense, and its documented. I understand how it can be surprising, but if you think about it for a second, it makes sense. The context created is meant to manage the lifecycle of the errgroup. Once the group is done, the ctx is done.
nasretdinov•6mo ago
It's only about context _returned by errgroup_ being cancelled, you shouldn't be overwriting it in the way in which it was used by an article, which is really hard to spot due to variable shadowing.
masklinn•6mo ago
> variable shadowing

There is no shadowing.

It's also harder to spot that this is a bad pattern because it's exactly what the package examples currently do.

dantillberg•6mo ago
I'd say it's fair to call this a footgun, though not a bug. The context is really only intended to apply to the goroutines. And Wait has to cancel the context to prevent a resource leak.

I suggest in general using function scoping to drive the lifetime of contexts, etc. This works also for defers and tracing spans in addition to the canonically shadowed `ctx` variable.

There is an old issue in the tracker proposing changes to alleviate this: https://github.com/golang/go/issues/34510. The original author (bcmills) of the errgroup package shared insight into the design choices/tradeoffs he made.

masklinn•6mo ago
> Shadowing is another concept that made this issue less visible.

There is no shadowing here, Go can only shadow in different scopes, `ctx` is just rebound (overwritten). Zig does not prevent reusing variables that I know. However I believe zig parameters are implicitly `const`, which would have prevented thoughtlessly updating the local in-place. Same in Rust.

> If you've ever heard of linear types, and never saw their utility, that's actually exactly what they are good for: a variable gets 'consumed' by a function, and the type system prevents us from using it after that point. Conceptually, g.Wait(ctx) consumes ctx and there is no point using this ctx afterwards.

I don't believe linear types would prevent this issue per-se since `errgroup.WithContext` specifically creates a derived context.

Depending on the affordance they might make the issue clearer but they also might not: a linear errgroup.WithContext could consume its input leaving you only with the sub-context and thinking little more of it, so you'd have to think to create derived context on the caller side. Would you think of this issue when doing that?

TBH this seems more of a design issue in errgroup's API: why is the context returned from the errgroup instead of being an attribute? That would limit namespace pollution and would make the relationship (and possible effects) much clearer. But I don't know what drove the API to be designed as it is.

But in all honesty I'd say the main error in the snippet is that `checkHaveIBeenPawned` swallows all http client errors, without even logging them. That is the part which struck out to me, it only returns an error if it positively finds that the password was a hit on HIBP. So you'd have hit the exact same issue if the `NewRequestWithContext` was otherwise malformed e.g. typo in the method or URL. And of course that points out to an other issue, this time with type-erased errors and error information not necessarily being programmatically accessible or at least idiomatically checked: I would assume the goal was to avoid triggering an error if HIBP is unavailable (DNS lookup or connection error).

eddythompson80•6mo ago
> why is the context returned from the errgroup instead of being an attribute?

It's a go style thing[1]. "Dont store context in a struct" is the general advice. Anybody seeing a ctx in a struct will flag the PR. I think golangci-lint does too.

The claim is that its confusing. Also you'll never see any std lib apis doing that. People just assume its a bad idea and don't do it. There are situations where it makes sense. Like operations that are described by a struct and you want to attach their context to those structs. A Boland developer will tell you "you're thinking in Java/Python/C#/JavaSctipt/etc you need to think in Go" and yes you can always rewrite the whole thing to be more go-like as in errgroup API. But it's just a style thing.

[1] https://go.dev/blog/context-and-structs

broken_broken_•6mo ago
Your are right about shadowing: I just checked and the go specification calls it “redeclaration” and it works as you described:

> Redeclaration does not introduce a new variable; it just assigns a new value to the original

I added a mention about that in the article. Thank you.

nikolayasdf123•6mo ago
omg. you are right. found multiple bugs just now thanks to this... they sould really improve this API of waitgroup/errgroup
nikolayasdf123•6mo ago
UPD: made a linter https://github.com/nikolaydubina/lint-errgroup-ctx
vultour•6mo ago
This seems like a terrible misunderstanding of the errgroup package? The entire point of the returned context is that it's cancelled if an error occurs, yet the author never uses it again until after he's done with the errgroup. The behaviour is also clearly documented in the only function exported by the package.
masklinn•6mo ago
> The entire point of the returned context is that it's cancelled if an error occurs, yet the author never uses it again until after he's done with the errgroup.

`Wait()` also does that. And the examples in the package documentation don't show the context as a way for the caller to be notified that things are done (that's what `Wait()` is for) but as a way for the callees (the callbacks passed to Do) to early abort.

This is mostly confirmed by the discussion dantillberg linked above, where someone suggests passing the errgroup's context down to the callbacks as parameter and the package author replies they don't do that because the lack of inference makes for nasty boilerplate (https://github.com/golang/go/issues/34510#issuecomment-53961...).

tonyhb•6mo ago
Yeah, just... like, don't use ctx from WithContext after the errgroup. WithContext is an API that specifically and explicitly cancels the context on error. It's absolutely optional. It's not a bug at all. It's using the wrong APIs and using a variable out of intended scope.
nickcw•6mo ago
I love errgroup, though I always use it like this

    g, gCtx := errgroup.WithContext(ctx)
And then use gCtx in the g.Go function calls.

That would have avoided the problem.

Perhaps worth a submission to https://staticcheck.dev/ ?

nikolayasdf123•6mo ago
I just made very simpler linter for this: https://github.com/nikolaydubina/lint-errgroup-ctx
nikolayasdf123•6mo ago
I made a simpler linter to detect this: https://github.com/nikolaydubina/lint-errgroup-ctx

An open replacement for the IBM 3174 Establishment Controller

https://github.com/lowobservable/oec
1•bri3d•2m ago•0 comments

The P in PGP isn't for pain: encrypting emails in the browser

https://ckardaris.github.io/blog/2026/02/07/encrypted-email.html
1•ckardaris•4m ago•0 comments

Show HN: Mirror Parliament where users vote on top of politicians and draft laws

https://github.com/fokdelafons/lustra
1•fokdelafons•4m ago•1 comments

Ask HN: Opus 4.6 ignoring instructions, how to use 4.5 in Claude Code instead?

1•Chance-Device•6m ago•0 comments

We Mourn Our Craft

https://nolanlawson.com/2026/02/07/we-mourn-our-craft/
1•ColinWright•8m ago•0 comments

Jim Fan calls pixels the ultimate motor controller

https://robotsandstartups.substack.com/p/humanoids-platform-urdf-kitchen-nvidias
1•robotlaunch•12m ago•0 comments

Exploring a Modern SMTPE 2110 Broadcast Truck with My Dad

https://www.jeffgeerling.com/blog/2026/exploring-a-modern-smpte-2110-broadcast-truck-with-my-dad/
1•HotGarbage•12m ago•0 comments

AI UX Playground: Real-world examples of AI interaction design

https://www.aiuxplayground.com/
1•javiercr•13m ago•0 comments

The Field Guide to Design Futures

https://designfutures.guide/
1•andyjohnson0•13m ago•0 comments

The Other Leverage in Software and AI

https://tomtunguz.com/the-other-leverage-in-software-and-ai/
1•gmays•15m ago•0 comments

AUR malware scanner written in Rust

https://github.com/Sohimaster/traur
3•sohimaster•18m ago•1 comments

Free FFmpeg API [video]

https://www.youtube.com/watch?v=6RAuSVa4MLI
3•harshalone•18m ago•1 comments

Are AI agents ready for the workplace? A new benchmark raises doubts

https://techcrunch.com/2026/01/22/are-ai-agents-ready-for-the-workplace-a-new-benchmark-raises-do...
2•PaulHoule•23m ago•0 comments

Show HN: AI Watermark and Stego Scanner

https://ulrischa.github.io/AIWatermarkDetector/
1•ulrischa•23m ago•0 comments

Clarity vs. complexity: the invisible work of subtraction

https://www.alexscamp.com/p/clarity-vs-complexity-the-invisible
1•dovhyi•24m ago•0 comments

Solid-State Freezer Needs No Refrigerants

https://spectrum.ieee.org/subzero-elastocaloric-cooling
2•Brajeshwar•25m ago•0 comments

Ask HN: Will LLMs/AI Decrease Human Intelligence and Make Expertise a Commodity?

1•mc-0•26m ago•1 comments

From Zero to Hero: A Brief Introduction to Spring Boot

https://jcob-sikorski.github.io/me/writing/from-zero-to-hello-world-spring-boot
1•jcob_sikorski•26m ago•1 comments

NSA detected phone call between foreign intelligence and person close to Trump

https://www.theguardian.com/us-news/2026/feb/07/nsa-foreign-intelligence-trump-whistleblower
10•c420•27m ago•1 comments

How to Fake a Robotics Result

https://itcanthink.substack.com/p/how-to-fake-a-robotics-result
1•ai_critic•27m ago•0 comments

It's time for the world to boycott the US

https://www.aljazeera.com/opinions/2026/2/5/its-time-for-the-world-to-boycott-the-us
3•HotGarbage•27m ago•0 comments

Show HN: Semantic Search for terminal commands in the Browser (No Back end)

https://jslambda.github.io/tldr-vsearch/
1•jslambda•27m ago•1 comments

The AI CEO Experiment

https://yukicapital.com/blog/the-ai-ceo-experiment/
2•romainsimon•29m ago•0 comments

Speed up responses with fast mode

https://code.claude.com/docs/en/fast-mode
5•surprisetalk•33m ago•1 comments

MS-DOS game copy protection and cracks

https://www.dosdays.co.uk/topics/game_cracks.php
4•TheCraiggers•34m ago•0 comments

Updates on GNU/Hurd progress [video]

https://fosdem.org/2026/schedule/event/7FZXHF-updates_on_gnuhurd_progress_rump_drivers_64bit_smp_...
2•birdculture•34m ago•0 comments

Epstein took a photo of his 2015 dinner with Zuckerberg and Musk

https://xcancel.com/search?f=tweets&q=davenewworld_2%2Fstatus%2F2020128223850316274
14•doener•35m ago•2 comments

MyFlames: View MySQL execution plans as interactive FlameGraphs and BarCharts

https://github.com/vgrippa/myflames
1•tanelpoder•36m ago•0 comments

Show HN: LLM of Babel

https://clairefro.github.io/llm-of-babel/
1•marjipan200•36m ago•0 comments

A modern iperf3 alternative with a live TUI, multi-client server, QUIC support

https://github.com/lance0/xfr
3•tanelpoder•37m ago•0 comments