I think what we need is a tool for properly forking upstream modules and adjusting the dependencies accordingly (and of course, the adjustment can be undone when/if the upstream maintainer accepts and merges your change). Replace is problematic in many ways:
1. It doesn't propagate downstream. If module Z depends on module Y, and module Y depends on module X, and module X is faulty, it's logical for module Y to have a replace directive for a fixed version of module X. This does not affect module Z, which now subtly (or loudly, sometimes) breaks. That helps nobody. It's good if you have an application that you build in CI and ship to your own private servers, but pretty much useless for everyone else. (And people don't seem aware of this; the author of module Y thinks they've fixed the problem for their consumers, but hasn't.)
2. It doesn't compose. If module Z depends on module Y and module X, and module Y and module X depend on module W, and the authors of module X and module Y independently discover that module W is broken and develop separate fixes for it, the author of module Z really has no option to make their software work.
I think Rob Pike's "a little copying is better than a little dependency" is apt here. If you just copy the source code you want into your own application, the problem goes away. But, the problematic upstream dependencies are often large projects (Azure's API client is a big offender here; I've never successfully depended on it without a replace directive) that are impractical to simply copy-and-refactor. At some point, these upstream providers need to fix their shit or risk not being used.
This problem, by the way, is not unique to Go. I notice this problem come up with Javascript when a bunch of modules depend on faulty-module-0.0.1 with a security problem. faulty-module-0.1.0 is released with a fix for the security problem, but your app directly depends on neat-feature-1.2.3 and nifty-addon-23.47.1 and those modules break with faulty-module-0.1.0. So inevitably you show up at the issue tracker for neat-feature and nifty-addon where 6000 other people are yelling at the authors to release a version that depends on the fixed version of faulty-module, find that the authors aren't around, and are just sad because there's nothing you can do. Basically, depending on other people's software sucks, and so does copying their code into your application. go has the advantage of very clearly telling you "hey, you're fucked!" which annoys people, but you basically get into this situation no matter what programming language you use. It's just you might not know, which is scary. (I hope you use something like Sentry for your Javascript apps and have 100% test coverage.)
1. It doesn't propagate downstream. If module Z depends on module Y, and module Y depends on module X, and module X is faulty, it's logical for module Y to have a replace directive for a fixed version of module X. This does not affect module Z, which now subtly (or loudly, sometimes) breaks. That helps nobody. It's good if you have an application that you build in CI and ship to your own private servers, but pretty much useless for everyone else. (And people don't seem aware of this; the author of module Y thinks they've fixed the problem for their consumers, but hasn't.)
2. It doesn't compose. If module Z depends on module Y and module X, and module Y and module X depend on module W, and the authors of module X and module Y independently discover that module W is broken and develop separate fixes for it, the author of module Z really has no option to make their software work.
I think Rob Pike's "a little copying is better than a little dependency" is apt here. If you just copy the source code you want into your own application, the problem goes away. But, the problematic upstream dependencies are often large projects (Azure's API client is a big offender here; I've never successfully depended on it without a replace directive) that are impractical to simply copy-and-refactor. At some point, these upstream providers need to fix their shit or risk not being used.
This problem, by the way, is not unique to Go. I notice this problem come up with Javascript when a bunch of modules depend on faulty-module-0.0.1 with a security problem. faulty-module-0.1.0 is released with a fix for the security problem, but your app directly depends on neat-feature-1.2.3 and nifty-addon-23.47.1 and those modules break with faulty-module-0.1.0. So inevitably you show up at the issue tracker for neat-feature and nifty-addon where 6000 other people are yelling at the authors to release a version that depends on the fixed version of faulty-module, find that the authors aren't around, and are just sad because there's nothing you can do. Basically, depending on other people's software sucks, and so does copying their code into your application. go has the advantage of very clearly telling you "hey, you're fucked!" which annoys people, but you basically get into this situation no matter what programming language you use. It's just you might not know, which is scary. (I hope you use something like Sentry for your Javascript apps and have 100% test coverage.)