Skip to content
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

0.29 Release: NotSignedInError - Intermittent issue pulling PDFs #1337

Closed
rayanedlebi-jb opened this issue Jan 14, 2024 · 4 comments
Closed

Comments

@rayanedlebi-jb
Copy link

Describe the bug
Since the release of 0.29, pulling a PDF from a Tableau dashboard intermittently fails. Specific error is NotSignedInError (more details below). The issue having to do with concurrent runs using the same PAT has been ruled out, as part of my debugging involved generating a new token (which didn't resolve the issue).

Current workaround is to utilize 0.28 version instead of 0.29.

NotSignedInError: (b'<?xml version=\'1.0\' encoding=\'UTF-8\'?><tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api https://help.tableau.com/samples/en-us/rest_api/ts-api_3_21.xsd"><error code="401002"><summary>Unauthorized Access</summary><detail>Invalid authentication credentials were provided.</detail></error></tsResponse>', 'https://prod-useast-b.online.tableau.com/api/3.21/auth/signout')

Versions

  • Tableau Server version (or note if using Tableau Online): Tableau Online
  • Python version: 3.9.5
  • TSC library version: 0.29

To Reproduce
Issue is intermittent, but always happens with retrieving the pdf attribute of a ViewItem() object. Example code is below:

import tableauserverclient as tsc

# Tableau Creds
tableau_token_name = "TOKEN_NAME"
tableau_personal_access_token = "TOKEN_VALUE"
site_id = "SITE_ID"
server_url = "TABLEAU_URL"

# Workbook ID from Tableau
workbook_id = "WORKBOOK_ID"

# Authenticate to Tableau
tableau_authentication = tsc.PersonalAccessTokenAuth(token_name=tableau_token_name, personal_access_token=tableau_personal_access_token, site_id=site_id)
server = tsc.Server(server_address=server_url, use_server_version=True)

pdf_req_option = tsc.PDFRequestOptions(maxage=1)

# Login to Tableau
with server.auth.sign_in_with_personal_access_token(tableau_authentication):
    # Get workbook
    workbook = server.workbooks.get_by_id(workbook_id)

    # Get workbook URL
    workbook_web_url = workbook.webpage_url

    # Populate views of workbook
    server.workbooks.populate_views(workbook)

    # Get first view of workbook
    dashboard_view = workbook.views[0]

    # Populate image of the dashboard view
    server.views.populate_image(dashboard_view, image_req_option)

    # Get image of dashboard view
    dashboard_view_image = dashboard_view.image

    # Populate pdf of the dashboard view
    server.views.populate_pdf(dashboard_view, pdf_req_option)

    # Get pdf of the dashboard view 
    #### LINE THAT USUALLY CAUSES NotSignedInError ####
    dashboard_view_pdf = dashboard_view.pdf

# Log out of Tableau
server.auth.sign_out()

Results
Specific error:

NotSignedInError                          Traceback (most recent call last)
<command-xyz>
     24 
     25     # Get pdf of the dashboard view
---> 26     dashboard_view_pdf = dashboard_view.pdf
     27 
     28 # Log out of Tableau

/lib/python3.9/site-packages/tableauserverclient/server/endpoint/auth_endpoint.py in __exit__(self, exc_type, exc_val, exc_tb)
     25 
     26         def __exit__(self, exc_type, exc_val, exc_tb):
---> 27             self._callback()
     28 
     29     @property

/lib/python3.9/site-packages/tableauserverclient/server/endpoint/endpoint.py in wrapper(self, *args, **kwargs)
    289         def wrapper(self, *args, **kwargs):
    290             self.parent_srv.assert_at_least_version(version, self.__class__.__name__)
--> 291             return func(self, *args, **kwargs)
    292 
    293         return wrapper

/lib/python3.9/site-packages/tableauserverclient/server/endpoint/auth_endpoint.py in sign_out(self)
     83         if not self.parent_srv.is_signed_in():
     84             return
---> 85         self.post_request(url, "")
     86         self.parent_srv._clear_auth()
     87         logger.info("Signed out")

/lib/python3.9/site-packages/tableauserverclient/server/endpoint/endpoint.py in post_request(self, url, xml_request, content_type, parameters)
    246 
    247     def post_request(self, url, xml_request, content_type=XML_CONTENT_TYPE, parameters=None):
--> 248         return self._make_request(
    249             self.parent_srv.session.post,
    250             url,

/lib/python3.9/site-packages/tableauserverclient/server/endpoint/endpoint.py in _make_request(self, method, url, content, auth_token, content_type, parameters)
    163         if isinstance(server_response, Exception):
    164             raise server_response
--> 165         self._check_status(server_response, url)
    166 
    167         loggable_response = self.log_response_safely(server_response)

/lib/python3.9/site-packages/tableauserverclient/server/endpoint/endpoint.py in _check_status(self, server_response, url)
    184                 if server_response.status_code == 401:
    185                     # TODO: catch this in server.py and attempt to sign in again, in case it's a session expiry
--> 186                     raise NotSignedInError(server_response.content, url)
    187 
    188                 raise ServerResponseError.from_response(server_response.content, self.parent_srv.namespace, url)

I'll add comments to this Issue if anything further to report on this. Please let me know if any questions, thanks.

@Feromond
Copy link

I have the exact same issue after the latest changes made in version 0.29. I follow similar use case. I see the same error as was shown here. If I pin my tableau server client version to 0.28 then I have no problems.

`

datasource_id = datasource_dict.get(data_source_selection)

with server.auth.sign_in(tableau_auth):
    datasource = server.datasources.get_by_id(datasource_id)
    refreshed_datasource_job = server.datasources.refresh(datasource)
    print(f'Extract refresh task for datasource {datasource_id} has been started.')`

@bcantoni bcantoni added the bug label Jan 16, 2024
@bcantoni
Copy link
Contributor

bcantoni commented Jan 17, 2024

I think there's a general bug in 0.29 that can impact multiple different types of endpoints. I've written that up in #1342

One workaround as both have noted above is to revert back to 0.28.

Another option that should work with 0.29 is to change your code from using the with statement to the older linear style.

For example, from:

with server.auth.sign_in(tableau_auth):
    datasource = server.datasources.get_by_id(datasource_id)
    refreshed_datasource_job = server.datasources.refresh(datasource)
    print(f'Extract refresh task for datasource {datasource_id} has been started.')`

to:

server.auth.sign_in(tableau_auth)

datasource = server.datasources.get_by_id(datasource_id)
refreshed_datasource_job = server.datasources.refresh(datasource)
print(f'Extract refresh task for datasource {datasource_id} has been started.')`

@bcantoni
Copy link
Contributor

@rayanedlebi-jb @Feromond we have a new v0.30 release which we believe should fix this:
https://github.com/tableau/server-client-python/releases/tag/v0.30

@rayanedlebi-jb
Copy link
Author

Thank you @bcantoni - I'll test and let you know if any issues. I appreciate your prompt response to this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants