Closed
Description
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.