-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
session
of AioHttpTransport
is None
at runtime, despite what's ruled out from typing
#32309
Comments
So the EDIT: Although I'm unclear why in the above stack trace it mentions |
Hi @alexpovel, thank you for opening such a detailed issue and investigating the scenario! I'll tag some folks who can take a look and get back to you as soon as possible. For assigned folks: requesting a look from both Identity and Core since the issue is raised in the latter but associated with the former. |
Hi @alexpovel , had a few follow up questions for you:
|
Hi, thanks for getting back to me.
|
Hi @alexpovel We investigated the three of us @annatisch, @xiangyan99 and me, and concluded that you can end up in this scenario if your HTTP internal transport was closed, and then re-used a second time. This can be trigger by code like this for instance (pseudo-code): transport = azure.core.pipeline.transport.AiohttpTransport()
async with StorageClient(endpoint, transport=transport) as client:
client.do_something()
async with StorageClient(endpoint, transport=transport) as client:
client.do_something() # this will raise with your error
# or
async with azure.identity.aio.ManagerIdentity() as credential:
async with StorageClient(endpoint, credential) as client:
client.do_something()
async with StorageClient(endpoint, credential) as client:
client.do_something() # this will raise with your error You are probably not passing your own transport, so there may be a combination of clients embedded into each other with a context manager syntax that ends up in this situation, even if you didn't pass your own client. As our credentials class own their own pipeline, did you use your credential instance several times in several clients maybe? With a context manager syntax? Does any of that would make sense if you look at your app? If not, is there any way we can look into your code, to understand the combination of client creation you are doing? If you're willing to share your code, it doesn't have to be public (I can share my email). Thanks, |
Hi @alexpovel. Thank you for opening this issue and giving us the opportunity to assist. To help our team better understand your issue and the details of your scenario please provide a response to the question asked above or the information requested above. This will help us more accurately address your issue. |
Thanks for the swift feedback. Your analysis is spot-on. I stripped down my code to the bare essentials that should (not verified!) trigger the issue: from azure.identity.aio import DefaultAzureCredential
from azure.storage.blob import BlobType
from azure.storage.blob.aio import BlobClient
class AzureBlobStorage:
def __init__(
self,
storage_url: str,
container_name: str,
credential: DefaultAzureCredential | None = None,
) -> None:
self.storage_url = storage_url
self.container_name = container_name
if credential is None:
credential = DefaultAzureCredential()
self.credential = credential
async def store(self, name: str, data: bytes) -> None:
async with self.credential as credential:
async with BlobClient(
str(self.storage_url),
container_name=self.container_name,
blob_name=name,
#
# https://github.com/Azure/azure-sdk-for-python/issues/27704:
credential=credential, # pyright: ignore[reportGeneralTypeIssues]
) as client:
# No idea why Pylance/Pyright is throwing a fit here, `mypy` is happy.
# Put on new line so we're below line length limit.
await client.upload_blob( # pyright: ignore[reportUnknownMemberType]
data=data,
blob_type=BlobType.BLOCKBLOB,
)
As you can tell from the comments, typing this properly was challenging. The optional context managers for the
Once my error is identified and fixed, I'd argue the code in question still isn't correct (although that's subjective to some degree): azure-sdk-for-python/sdk/core/azure-core/azure/core/pipeline/transport/_aiohttp.py Lines 125 to 127 in 17494dd
This should probably be an assertion error or similar. A The only raising there is in the azure-sdk-for-python/sdk/core/azure-core/azure/core/pipeline/transport/_aiohttp.py Lines 96 to 97 in 17494dd
but that covers a different case and can logically fall through with a |
Thanks for sharing the code. async def store(self, name: str, data: bytes) -> None:
async with self.credential as credential:
async with BlobClient(
str(self.storage_url),
container_name=self.container_name,
blob_name=name,
#
# https://github.com/Azure/azure-sdk-for-python/issues/27704:
credential=credential, # pyright: ignore[reportGeneralTypeIssues]
) as client:
# No idea why Pylance/Pyright is throwing a fit here, `mypy` is happy.
# Put on new line so we're below line length limit.
await client.upload_blob( # pyright: ignore[reportUnknownMemberType]
data=data,
blob_type=BlobType.BLOCKBLOB,
) Here you use context manager for the credential. Every time you run it, the exist of If you need to call the store method multiple times, you need to keep the credential open. |
Hi @alexpovel. Thank you for opening this issue and giving us the opportunity to assist. We believe that this has been addressed. If you feel that further discussion is needed, please add a comment with the text "/unresolve" to remove the "issue-addressed" label and continue the conversation. |
Hi @alexpovel, since you haven’t asked that we |
I'm hitting this too, similar situation, but with CosmosClient. I was using context manger for the credentials like: async with credentials.get_credential_async() as credential:
if MANAGED_IDENTITY_CLIENT_ID:
logger.debug("Connecting with managed identity")
cosmos_client = CosmosClient(
url=STATE_STORE_ENDPOINT,
credential=credential
) I've switched this to: credential = get_credential()
if MANAGED_IDENTITY_CLIENT_ID:
logger.debug("Connecting with managed identity")
cosmos_client = CosmosClient(
url=STATE_STORE_ENDPOINT,
credential=credential
) But I still find I get an exception on this line on some calls when reusing the
We are storing the client in application state,, hence I can see how the credential will go out of context, this was working when using a master key, but now we have moved to MSI are hitting this issue. Can you provide an example as to how to "keep the credential open"? Thank you. |
Actually I see the same behaviour when using a key, so not down to credentials is our case:
When it fails We are using |
azure-identity
(probably not relevant, error is incore
?)1.14.0
3.11.4
Describe the bug
Using
ManagedIdentityCredential
:azure-sdk-for-python/sdk/identity/azure-identity/azure/identity/aio/_credentials/managed_identity.py
Line 21 in 17494dd
it at some point reaches out to actually get its token, reaching:
azure-sdk-for-python/sdk/core/azure-core/azure/core/pipeline/transport/_aiohttp.py
Lines 125 to 127 in 17494dd
at which point it blows up, as
self.session
isNone
in my case. The impossibility ruled out on the type-level with a forced cast is possible after all at runtime, it looks like!To Reproduce
Steps to reproduce the behavior:
Use
async
version ofManagedIdentityCredential
, provide credentials in some formDeploy to Container App Jobs (my Job has Managed Identity assigned: both user- as well as system-assigned raised the above issue)
Observe stack trace:
Expected behavior
self.session
is neverNone
at that point, so entering the async context manager works, so authentication succeeds. If there's asession
issue, it should be raised earlier (as the comment suggests).Additional context
azure.core.exceptions.ServiceRequestError: Server disconnected
. Nevertheless, that's a different issue and I'll open a separate ticket. I reckon given this edge case, the typing andNone
checks should still be sound and not cause a runtime failure.await c.upload_blob( # pyright: ignore[reportUnknownMemberType]
.c
is the result ofasync with azure.storage.blob.aio.BlobClient(...) as c
. This passesmypy
, so while my code also has a typing issue I am force-ignoring, I hope it's not the cause (my code works in principle, just not when deploying to Container App Jobs).The text was updated successfully, but these errors were encountered: