-
-
Notifications
You must be signed in to change notification settings - Fork 52
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
Token expired #514
Comments
Could you post the code that you're using to save and reuse sessions? For reference, this is the implementation of sessions in the Astronomy feeds, and I don't think we've ever had this issue. It's a bit bigger than the example in the ATProto SDK docs as it also saves to a file. |
Do you happen to change or delete app passwords? do you have only 1 script? Do you save your session in a disc file? do you use the same file with the saved session from many places? |
Thank you both for your answers. @emilyhunt: I used the code provided in the respective example in this repo. @MarshalX: I never changed or deleted the app password since I created it. I have in fact 2 scripts. Both are using the session reuse system from the example you provided but with different session files. One script runs every 30 minutes, the other is continuously running and sleeps in-between calls. The calls here are quite a lot actually (looking for unread messages every 2 secs) but the rate-limit doesn't seem to be the problem, as the error message states that there's quite a lot remaining. As a test I just deleted the session file and then the script worked. So I suppose it saved a session with a revoked token? |
@Ph-St do you use different app passwords for each script? |
@MarshalX No, they use the same app password. Should I create one for each instead? |
@Ph-St you could try. I am not sure how backend handles many access tokens for one app password |
@MarshalX OK, I will try and report back. |
@MarshalX Just checked the log and there are fresh Token expired messages, so getting separate app passwords didn't help. Do you have any ideas how I could debug this further? |
@Ph-St welp, first of all, as @emilyhunt asked, it would be great to see the code. are you sure that this is the exact copy of an example from the repo? for debug purposes highly recommend starting with debug lvl logging from httpx (lib to perform requests). it will show how and when the session is created/refreshed etc |
Ok sure, so here are the relevant parts of the code: def get_session() -> Optional[str]:
try:
with open('session_requests_bs.txt', encoding='UTF-8') as f:
return f.read()
except FileNotFoundError:
return None
def save_session(session_string: str) -> None:
with open('session_requests_bs.txt', 'w', encoding='UTF-8') as f:
f.write(session_string)
def on_session_change(event: SessionEvent, session: Session) -> None:
print('Session changed:', event, repr(session))
if event in (SessionEvent.CREATE, SessionEvent.REFRESH):
print('Saving changed session')
save_session(session.export())
def init_client() -> Client:
client = Client()
client.on_session_change(on_session_change)
session_string = get_session()
if session_string:
print('Reusing session')
client.login(session_string=session_string)
else:
# Login
username="xxxxxxxx"
password="xxxxxxxx"
print('Creating new session')
client.login(username, password)
return client
async def check_messages_periodically():
while True:
await check_for_new_messages()
await asyncio.sleep(2)
async def check_for_new_messages():
# Initialize chat
dm_client = client.with_bsky_chat_proxy()
# create shortcut to convo methods
dm = dm_client.chat.bsky.convo
# Collect conversations with unread messages
unread_convos = []
convo_list = dm.list_convos()
for convo in convo_list.convos:
if convo.unread_count > 0:
unread_convos.append(convo)
if len(unread_convos) > 0:
print(f'There are {(len(unread_convos))} conversation with unread messages.')
for counter,ur_convo in enumerate(unread_convos, start=1):
# Getting data from last messages
print(f'Conversation {counter} ID: {ur_convo.id}')
messages = dm.get_messages(models.ChatBskyConvoGetMessages.Params(convoId=ur_convo.id))
last_message_sender_did=messages['messages'][0]['sender']['did']
last_message_text=messages['messages'][0]['text']
last_message_id=messages['messages'][0]['id']
print(f'Last sender DID: {last_message_sender_did}, last text: {last_message_text}, last id: {last_message_id}')
# Creating reply to message, no API calls here
# ...
# Send reply
convo = dm.get_convo_for_members(models.ChatBskyConvoGetConvoForMembers.Params(members=[notification_account]),).convo
dm.send_message(models.ChatBskyConvoSendMessage.Data(convo_id=convo.id,message=models.ChatBskyConvoDefs.MessageInput(text=reply,),))
# Setting message status to read
response = dm.update_read({"convoId": ur_convo.id,"messageId": last_message_id})
if __name__ == '__main__':
client = init_client()
asyncio.run(check_messages_periodically()) Can you spot anything problematic? |
oh i spot it. i think that's because of #371 bug :( lemme try to describe what happens:
tldr; when you perform requests using upd. as a hacky and fast solution i suggest performing any requests with # send any request to trigger the SDK session refreshing mechanism
client.get_timeline() # we do not care about the returned value
# Initialize chat with refreshed tokens
dm_client = client.with_bsky_chat_proxy()
# create shortcut to convo methods
dm = dm_client.chat.bsky.convo |
@MarshalX I see! I added your fix. Let's see whether that solves it. Many thanks for the help! |
@MarshalX Can't see any more errors in the log. Thanks again! |
According to the documentation, the SDK should take care of token management and refresh tokens before they expire. Nevertheless, I'm getting lots of "Token expired" errors, such as this:
atproto_client.exceptions.BadRequestError: Response(success=False, status_code=400, content=XrpcError(error='ExpiredToken', message='Token has been revoked'), headers={'x-powered-by': 'Express', 'access-control-allow-origin': '*', 'cache-control': 'private', 'vary': 'Authorization, Accept-Encoding', 'ratelimit-limit': '3000', 'ratelimit-remaining': '2925', 'ratelimit-reset': '1736759405', 'ratelimit-policy': '3000;w=300', 'content-type': 'application/json; charset=utf-8', 'content-length': '59', 'etag': 'W/"3b-elKlVAnBs8eAB241ckLlScv0EUs"', 'date': 'Mon, 13 Jan 2025 09:09:25 GMT', 'keep-alive': 'timeout=90', 'strict-transport-security': 'max-age=63072000'})
My script runs every 30 minutes, just makes a few API calls and I'm saving and reusing sessions as suggested in the documentation. Still, I'm getting errors like the above. Any idea what I could be doing wrong?
The text was updated successfully, but these errors were encountered: