Skip to content

Subscription creation without pre-existing schedule item fails (user error?) #1543

Closed as not planned

Description

@CodingOnWindowsOS

Describe the bug
I am attempting to create a subscription to a workbook using a schedule that doesn't exist at creation time. To perform the same action using Tableau Cloud/Server front-end, the user would configure the subscription by specifying the target type (view or entire workbook), format, subject, and schedule.

Versions
Tableau Cloud
Python 3.12.3
TSC library version 3.24

To Reproduce

 # Sign-in to server.
  with server.auth.sign_in(tableau_auth):
      # Ensure the most recent Tableau REST API version is used.
      server.use_highest_version()
      # Retrieve the user requiring the new subscription.
      user = server.users.filter(name='cmp160130@gmail.com')
      # Retreive the subscription's content (e.g., workbook, view)
      target = server.workbooks.filter(name='North America Sales')

      new_subscription = tsc.SubscriptionItem(
          subject='North America Sales (demo)',
          schedule_id=tsc.ScheduleItem(
              name=None,
              priority=None,
              schedule_type=None,
              execution_order=None,
              interval_item=tsc.DailyInterval(time(0),
                  24.0, 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'
              )
          ),
          user_id=user[0].id,
          target=tsc.Target(target[0].id, target_type='Workbook')
      )

      # Subscribe the user to the target content.
      server.subscriptions.create(subscription_item=new_subscription)

Results
What are the results or error messages received?
TypeError: cannot serialize <Schedule#None "None" <DailyInterval start=00:00:00 interval=(24.0, 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday')>> { _created_at: None, _end_schedule_at: None, _id: None, _next_run_at: None, _state: None, _updated_at: None, interval_item: <DailyInterval start=00:00:00 interval=(24.0, 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday')>, _execution_order: None, _name: None, _priority: None, _schedule_type: None} (type ScheduleItem)

If I swap out the subscription item configuration above for the following that uses a pre-existing schedule, then it works fine.

new_subscription = tsc.SubscriptionItem(
    subject='North America Sales (demo)',
    schedule_id='f3dcaf7a-9668-4eb2-8c20-2f7c21e82744',
    user_id=user[0].id,
    target=tsc.Target(target[0].id, target_type='Workbook')
)

Activity

  1. jacalata commented on Dec 8, 2024

    @jacalata
    Contributor

    I believe this is indeed a requirement, but we could return a better error from the server, and tsc should give a hint too.

  2. CodingOnWindowsOS commented on Dec 8, 2024

    @CodingOnWindowsOS
    Author

    Thank you for the support!

    The odd part is that I can manually create a subscription to the workbook using the front-end features, subsequently query that subscription using TSC, and observe the schedule ID, name, priority, etc. are None for that subscription. The date and time the subscription is configured to fire off is populated, but no schedule ID. That's the behavior I am trying to replicate when creating them using TSC and am at a loss as to why it doesn't work.

    I also tried copying the schedule item from a preexisting subscription that I manually configured. It also fails. I'll provide a snippet of the subscription object returned where the schedule ID is not populated and corresponds to the subscription mentioned above tomorrow.

    Thanks again!

  3. CodingOnWindowsOS commented on Dec 8, 2024

    @CodingOnWindowsOS
    Author

    Manual creation of subscription to workbook.
    subscription_image_1
    subscription_image_2

    Below is the subscription retrieved after creating it manually using the front-end. The manual creation process is shown within the two images.
    <Subscription#0f1ab430-5b67-45fa-93f9-e2ee9e465601 subject(Daily Sales (testing)) schedule_id(None) user_id(9390ecd3-2278-467c-a636-5486afd3dec1) target(<Target#5faf8999-1ad8-4f0d-b337-b72a3882a418, Workbook>)

    Using subscription.dict:
    {'_id': '0f1ab430-5b67-45fa-93f9-e2ee9e465601', '_attach_image': False, '_attach_pdf': True, 'message': 'Testing', 'page_orientation': 'PORTRAIT', 'page_size_option': 'LETTER', 'schedule_id': None, '_send_if_view_empty': True, 'subject': 'Daily Sales (testing)', '_suspended': False, 'target': <Target#5faf8999-1ad8-4f0d-b337-b72a3882a418, Workbook>, 'user_id': '9390ecd3-2278-467c-a636-5486afd3dec1', 'schedule': [<Schedule#None "None" <DailyInterval start=00:00:00 interval=(24.0, 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday')>> { _created_at: None, _end_schedule_at: None, _id: None, _next_run_at: None, _state: None, _updated_at: None, interval_item: <DailyInterval start=00:00:00 interval=(24.0, 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday')>, _execution_order: None, _name: None, _priority: None, _schedule_type: None}]}

    Accessing the schedule attribute of the subscription:
    [<Schedule#None "None" <DailyInterval start=00:00:00 interval=(24.0, 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday')>> { _created_at: None, _end_schedule_at: None, _id: None, _next_run_at: None, _state: None, _updated_at: None, interval_item: <DailyInterval start=00:00:00 interval=(24.0, 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday')>, _execution_order: None, _name: None, _priority: None, _schedule_type: None}]

    Notice the schedule ID is none as are the vast majority of attributes related to the schedule aside from those necessary for the subscription. I am hoping to achieve the same functionality using TSC. I hope that makes sense! Am I just doing it wrong in my original code example or is something else amiss? @jacalata

  4. jacalata commented on Jan 3, 2025

    @jacalata
    Contributor

    OK, looks like I didn't read your first code closely enough. You have this line, where you assign an entire schedule object to the attribute schedule_id , which is only expecting a luid like 0f1ab430-5b67-45fa-93f9-e2ee9e465601:

    
     schedule_id=tsc.ScheduleItem(
                  name=None,
                  priority=None,
                  schedule_type=None,
                  execution_order=None,
                  interval_item=tsc.DailyInterval(time(0),
                      24.0, 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'
                  )
    
    

    You want to create the SubscriptionItem without setting a schedule_id, and then do
    new_subscription.schedule = tsc.ScheduleItem(....

  5. added
    help wantedA user needs help, may be a mistake, a bug or a feature request
    on Jan 3, 2025
  6. GwenVCX commented on Jan 28, 2025

    @GwenVCX

    I am having the same issue

  7. hahu66 commented on Mar 11, 2025

    @hahu66

    I am still getting an error trying to create a subscription on Tableau Cloud v2025.1.0

    Versions
    Tableau Cloud (dub01.online.tableau.com) 2025.1.0 build 20251.25.0305.2339
    Python 3.12.8
    REST API 3.25
    TSC library version 0.36

    Code:

    target = tsc.Target('09c7862b.....-d59fbbd2983a','View')
    interval_item = tsc.WeeklyInterval(time(12,0), tsc.IntervalItem.Day.Wednesday)
    sch = tsc.ScheduleItem(name=None,priority=None,schedule_type=None,execution_order=None,interval_item=interval_item)
    #schedule_id = '153eeedd-.....-ffc39ae91373'
    schedule_id = ''
    user_id='427385fb-.....-8d1f29c1345b'
    subject = 'Waiting for approval'
    new_sub = tsc.SubscriptionItem(subject=subject, user_id=user_id, target=target, schedule_id=None)
    #new_sub = tsc.SubscriptionItem(subject=subject, user_id=user_id, target=target, schedule_id=schedule_id)
    new_sub.schedule = sch
    new_sub.message = 'manual test'
    new_sub.attach_image = False
    new_sub.attach_pdf = True
    new_sub.page_orientation = 'PORTRAIT'
    new_sub.page_size_option = 'A4'
    new_sub.send_if_view_empty = True
    new_sub.suspended = False
    new_sub = server.subscriptions.create(subscription_item=new_sub)
    

    So creating with 'schedule_id=None' fails with the error below.
    Also fails with 'schedule_id='' or when leaving schedule_id out of the SubscriptionItem.

    I am able to create it with an existing schedule_id . But them you can not change the frequency anymore on TblCloud.
    Just to verify all other parameters and settings in the Subscription Item are correct.
    (All specified IDs used are real and existing, only masked in this post)

    Traceback (most recent call last):
      File "c:\Programs\Python312\Lib\xml\etree\ElementTree.py", line 1027, in _escape_attrib
        if "&" in text:
           ^^^^^^^^^^^
    TypeError: argument of type 'NoneType' is not iterable
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "D:\MyPyProjects\Mig_SDK_Fixes\env\Lib\site-packages\tableauserverclient\server\endpoint\endpoint.py", line 274, in wrapper
        return func(self, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "D:\MyPyProjects\Mig_SDK_Fixes\env\Lib\site-packages\tableauserverclient\server\endpoint\subscriptions_endpoint.py", line 48, in create
        create_req = RequestFactory.Subscription.create_req(subscription_item)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "D:\MyPyProjects\Mig_SDK_Fixes\env\Lib\site-packages\tableauserverclient\server\request_factory.py", line 37, in wrapper
        func(self, xml_request, *args, **kwargs)
      File "D:\MyPyProjects\Mig_SDK_Fixes\env\Lib\site-packages\tableauserverclient\server\request_factory.py", line 1226, in create_req
        return ET.tostring(xml_request)
               ^^^^^^^^^^^^^^^^^^^^^^^^
      File "c:\Programs\Python312\Lib\xml\etree\ElementTree.py", line 1084, in tostring
        ElementTree(element).write(stream, encoding,
      File "c:\Programs\Python312\Lib\xml\etree\ElementTree.py", line 729, in write
        serialize(write, self._root, qnames, namespaces,
      File "c:\Programs\Python312\Lib\xml\etree\ElementTree.py", line 892, in _serialize_xml
        _serialize_xml(write, e, qnames, None,
      File "c:\Programs\Python312\Lib\xml\etree\ElementTree.py", line 892, in _serialize_xml
        _serialize_xml(write, e, qnames, None,
      File "c:\Programs\Python312\Lib\xml\etree\ElementTree.py", line 885, in _serialize_xml
        v = _escape_attrib(v)
            ^^^^^^^^^^^^^^^^^
      File "c:\Programs\Python312\Lib\xml\etree\ElementTree.py", line 1050, in _escape_attrib
        _raise_serialization_error(text)
      File "c:\Programs\Python312\Lib\xml\etree\ElementTree.py", line 1004, in _raise_serialization_error
        raise TypeError(
    TypeError: cannot serialize None (type NoneType)
    
  8. github-actions commented on Jul 24, 2026

    @github-actions

    This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. If this is still relevant, please comment to keep it open.

  9. jacalata commented on Jul 30, 2026

    @jacalata
    Contributor

    Digging back into this, the TypeError: cannot serialize None (type NoneType) that @hahu66 hit is a real TSC bug. SubscriptionRequest.create_req unconditionally writes id=None into <schedule> when schedule_id is None (no guard, unlike the sibling update_req), and it does not serialize the .schedule object at all. Tableau Cloud's POST /subscriptions endpoint accepts an inline <schedule frequency="..."><frequencyDetails>...</frequencyDetails></schedule> payload (no schedule ID required), which is what the UI produces when you create an "on-schedule" subscription without a pre-existing schedule LUID. TSC only knows how to emit the on-prem-Server payload shape.

    That gap is the same one tracked in #1373 (Cloud-specific subscription requests) and, from the read side, #1627. Rather than have three copies of the same conversation, I'm closing this one and pointing at #1373 for the fix. If you want to follow along or add repro details, subscribe there.

    Thanks for the detailed writeups — they were what let me nail down the exact code path (see request_factory.py:1345-1347 on development).

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedA user needs help, may be a mistake, a bug or a feature requeststale

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions