I think what is happening here, is you’re writing the file twice hence the duplicate error. environment.etc.*.source = is expecting a path and it will write the contents of the path to the store and link it into /etc/ for you. You’re returning a derivation which I believe can be interpolated as a path. So when you call pkgs.runCommand which is a simple builder it’s also writing the string to the store. Since they have the exact same contents the inputs are identical and so is the hash.
If you make build-sway-config.nix a function that directly returns a string instead of using pkgs.runCommand, you could call it like this to get the effect I think you want:
That aside, the way you have written it currently will cause the symlink at /etc/sway/config to point to a directory, which is probably not what you want write directly to $out in your build script rather than creating $out as a directory to fix that, or make it more concise using writeText: