Flakes evaluate in pure mode by default. builtins.getEnv returns an empty string, absolute paths outside the flake cannot be read, the network is unavailable except through locked inputs, and builtins.currentSystem is unavailable. This is what makes a flake's output reproducible from its lock file alone.
Code ported from a default.nix frequently relies on exactly these. A derivation that read a token from the environment or referenced ~/.config fails with an empty value or an access error rather than a clear explanation.
--impure disables purity for a single evaluation and is the right escape hatch for local experimentation, never for anything committed. The supported alternatives are to add whatever was being read as a flake input, to pass values through --argstr on the underlying builder, or, for system identification, to use the system argument that flake-utils or an explicit forAllSystems helper provides instead of currentSystem. Impure evaluation also disables the eval cache, so it is noticeably slower on repeated runs.