Skip to content

Conversation

@mbrancato
Copy link
Contributor

Treat empty strings as if the env var was not set. This fixes an issue where an environment variable for GOOGLE_APPLICATION_CREDENTIALS is set, but it empty. Because the default sentinel is None, the auth library attempts to load this file. Some systems can set or update an env var, but not unset an env var (e.g. Docker).

Fixes: googleapis/python-pubsub#983

@mbrancato mbrancato requested review from a team as code owners August 22, 2023 16:30
@google-cla
Copy link

google-cla bot commented Aug 22, 2023

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@mbrancato mbrancato requested a review from BigTailWolf August 17, 2024 03:23
@chalmerlowe chalmerlowe requested a review from a team as a code owner January 5, 2026 14:24
@chalmerlowe chalmerlowe self-assigned this Jan 5, 2026
@chalmerlowe chalmerlowe added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jan 5, 2026
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jan 5, 2026
@parthea parthea added kokoro:force-run Add this label to force Kokoro to re-run the tests. kokoro:run Add this label to force Kokoro to re-run the tests. labels Jan 5, 2026
@yoshi-kokoro yoshi-kokoro removed kokoro:run Add this label to force Kokoro to re-run the tests. kokoro:force-run Add this label to force Kokoro to re-run the tests. labels Jan 5, 2026
@chalmerlowe chalmerlowe added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jan 7, 2026
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jan 7, 2026
@chalmerlowe chalmerlowe added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jan 9, 2026
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jan 9, 2026
Copy link
Contributor

@chalmerlowe chalmerlowe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM


cloud_sdk_adc_path = _cloud_sdk.get_application_default_credentials_path()
explicit_file = os.environ.get(environment_vars.CREDENTIALS)
explicit_file = os.environ.get(environment_vars.CREDENTIALS, "")
Copy link
Collaborator

@daniel-sanche daniel-sanche Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I like using "" to represent the empty state. That seems like it could lead to confusing situations down the line. Instead, I'd recommend:

  1. changing this line to os.environ.get(environment_vars.CREDENTIALS) or None, which will replace empty strings with None

or

  1. use if explicit_file: in place of the checks, which will respond to None and empty strings the same way, since both are falsy

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Daniel:

Thanks for this comment. I considered similar ideas when evaluating this, and this is the conclusion I came to:

The variable explicit_file is a local variable within _get_explicit_environ_credentials(), so no external API is changed or affected and the way the code is currently written, it must be a str. Why? Because of the default behavior of the .get() method on a dict and because of the return object from .get_application_default_credentials_path() which is a str.

dict .get()

Environmental variables are stored as strings AND if the CREDENTIALS variable is not found, we return an empty string as the default value. There is no reason to return a None, it serves no additional purpose in the limited uses that we have for the variable explicit_file.

explicit_file = os.environ.get(environment_vars.CREDENTIALS, "")

_cloud_sdk.get_application_default_credentials_path()

This function returns a string.

def get_application_default_credentials_path():
    """Gets the path to the application default credentials file.

    The path may or may not exist.

    Returns:
        str: The full path to application default credentials.
    """

In the comparision, we are checking to see IF explicit_file was unset AND if not, whether the path matches the path referenced by cloud_sdk_adc_path. There is no need OR reason to prefer None over the empty string.

if explicit_file != "" and explicit_file == cloud_sdk_adc_path:

So why use the empty string?

Old Behavior: Defaulted to None if unset.
New Behavior: Defaults to "" if unset (via os.environ.get(..., "")).
Result: The logic now treats "unset" and "set to empty string" identically (as ""). The check explicit_file != "" correctly handles both cases (unset OR empty string) by skipping the file load, which prevents a crash. cloud_sdk_adc_path always returns a string path, so the comparison remains safe.

Before I had fully worked through the above logic, I had considered something such as:

if explicit_file not in {None, ""} and feel that while if explicit_file not in {None, ""} OR similar patterns (such as you recommend) where we look for both is a valid defensive pattern, the current PR's approach is slightly cleaner because it enforces type consistency. If we initialize explicit_file with a default of "", the variable is always a str, avoiding mixed types (Optional[str]). The current implementation explicit_file != "" is correct given the initialization change.

Copy link
Collaborator

@daniel-sanche daniel-sanche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider my comment, but I think this is also ok to merge as-is

@chalmerlowe chalmerlowe added kokoro:force-run Add this label to force Kokoro to re-run the tests. automerge Merge the pull request once unit tests and other checks pass. labels Jan 9, 2026
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jan 9, 2026
@gcf-merge-on-green gcf-merge-on-green bot merged commit bfc07e1 into googleapis:main Jan 9, 2026
15 checks passed
@gcf-merge-on-green gcf-merge-on-green bot removed the automerge Merge the pull request once unit tests and other checks pass. label Jan 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Default credentials fail to detect running on GCP when ADC env var is empty

6 participants