Today I tried to automate pushing to a Git repository from a Docker container. And like many others I failed with an error:

$ git push
No user exists for uid 2918
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Following best practices I was running the container under a random UID to drop root privileges, and of course there was no user with that UID in the system. I don't think that's egregious enough to warrant an error instead of a warning from git push, so I've started digging.

I was very surprised to learn where this error comes from:

/*
 * openssh/ssh.c: Main program for the ssh client.
 */
int main(int ac, char **av) {

    // ...lines omitted...

    /* Get user data. */
    pw = getpwuid(getuid());
    if (!pw) {
        logit("No user exists for uid %lu", (u_long)getuid());
        exit(255);
    }

getuid() is pretty self-explanatory, it returns UID of current user. Afterwards getpwuid() attempts to fetch data for the provided UID from /etc/passwd. It fails, of course, and returns NULL. OpenSSH client treats that as a show stopper and exits with an error.

I was hoping that finding the place where error is generated will help me to come up with a setup that avoids problematic code branch altogether, but no luck this time. It's straight in the main() function of ssh client, no conditional branching whatsoever.

I will be looking into generating a bogus /etc/passwd entry on-the-fly prior to launching my application in container. I would very much like to avoid hardcoding the UID at build time. (UPD: proper workaround would be to use libnss-wrapper like postgres does)

Meanwhile, here is a punchline for you:

When current UID is not in /etc/passwd OpenSSH client can not even print a usage message:

$ ssh
No user exists for uid 3432

$ ssh --help
No user exists for uid 3432