Tweepy Python library "media_ids parameter is invalid" and "Tweet must not have more than 4 mediaIds" when submitting status update. Codes 44 and 324
Question: I have some pretty simple code for uploading images to Twitter via the Tweepy
library and then posting a status update using the returned media ids. I've
seen a lot of questions on this topic here but none that have solved my
problem. Code is as follows.

    
    
    import tweepy
    from configparser import SafeConfigParser
    
    config = SafeConfigParser()
    config.read('/var/www/config.ini')
    
    CONSUMER_KEY = config.get('twitter', 'CONSUMER_KEY')
    CONSUMER_SECRET = config.get('twitter', 'CONSUMER_SECRET')
    ACCESS_KEY = config.get('twitter', 'ACCESS_KEY')
    ACCESS_SECRET = config.get('twitter', 'ACCESS_SECRET')
    
    auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
    auth.set_access_token(ACCESS_KEY, ACCESS_SECRET)
    api = tweepy.API(auth)
    
    file = open('/var/www/photo1.jpeg', 'rb')
    r1 = api.media_upload(filename='/var/www/photo1.jpeg', file=file)
    print(r1)
    print(r1.media_id_string)
    file = open('/var/www/photo2.jpeg', 'rb')
    r2 = api.media_upload(filename='/var/www/photo2.jpeg', file=file)
    print(r2)
    print(r2.media_id_string)
    media_ids = r1.media_id_string + ', ' + r2.media_id_string
    print(media_ids)
    api.update_status(media_ids=media_ids, status="Test Tweet")
    

When executing this script I get the following error at the last line

    
    
    Traceback (most recent call last):
      File "test2.py", line 26, in <module>
        api.update_status(media_ids=media_ids, status="Test Tweet")
      File "/usr/local/lib/python3.4/dist-packages/tweepy/api.py", line 194, in update_status
        )(post_data=post_data, *args, **kwargs)
      File "/usr/local/lib/python3.4/dist-packages/tweepy/binder.py", line 245, in _call
        return method.execute()
      File "/usr/local/lib/python3.4/dist-packages/tweepy/binder.py", line 229, in execute
        raise TweepError(error_msg, resp, api_code=api_error_code)
    tweepy.error.TweepError: [{'message': 'media_ids parameter is invalid.', 'code': 44}]
    

The 2 media upload requests return the following objects:

    
    
    Media(media_id=728190961679929344, size=879715, expires_after_secs=86400,
    media_id_string='728190961679929344', _api=<tweepy.api.API object at
    0x7ffaf4d8fda0>, image={'h': 4000, 'w': 5000, 'image_type': 'image/jpeg'})
    

and

    
    
    Media(media_id=728190987122532353, size=17489, expires_after_secs=86400,
    media_id_string='728190987122532353', _api=<tweepy.api.API object at
    0x7ffaf4d8fda0>, image={'h': 369, 'w': 640, 'image_type': 'image/jpeg'})
    

from which I extract the media ids of `728190961679929344` and
`728190987122532353` as strings through the media_id_string variable and
combine them into a single string separated by commas i.e.
`728190961679929344, 728190987122532353`. I've tried with and without the
space, in single and double quotations, singularly quoted and quoting the
entire string but nothing works.

If instead I try just update with a single image id as in the following

    
    
    import tweepy
    from configparser import SafeConfigParser
    
    config = SafeConfigParser()
    config.read('/var/www/config.ini')
    
    CONSUMER_KEY = config.get('twitter', 'CONSUMER_KEY')
    CONSUMER_SECRET = config.get('twitter', 'CONSUMER_SECRET')
    ACCESS_KEY = config.get('twitter', 'ACCESS_KEY')
    ACCESS_SECRET = config.get('twitter', 'ACCESS_SECRET')
    
    auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
    auth.set_access_token(ACCESS_KEY, ACCESS_SECRET)
    api = tweepy.API(auth)
    
    file = open('/var/www/photo1.jpeg', 'rb')
    r1 = api.media_upload(filename='/var/www/photo1.jpeg', file=file)
    print(r1)
    print(r1.media_id_string)
    file = open('/var/www/photo2.jpeg', 'rb')
    r2 = api.media_upload(filename='/var/www/photo2.jpeg', file=file)
    print(r2)
    print(r2.media_id_string)
    media_ids = r1.media_id_string + ', ' + r2.media_id_string
    print(media_ids)
    api.update_status(media_ids=r1.media_id_string, status="Test Tweet")
    

I get the following error again at the last line

    
    
    Traceback (most recent call last):
      File "test2.py", line 26, in <module>
        api.update_status(media_ids=r1.media_id_string, status="Test Tweet")
      File "/usr/local/lib/python3.4/dist-packages/tweepy/api.py", line 194, in update_status
        )(post_data=post_data, *args, **kwargs)
      File "/usr/local/lib/python3.4/dist-packages/tweepy/binder.py", line 245, in _call
        return method.execute()
      File "/usr/local/lib/python3.4/dist-packages/tweepy/binder.py", line 229, in execute
        raise TweepError(error_msg, resp, api_code=api_error_code)
    tweepy.error.TweepError: [{'message': 'Tweet must not have more than 4 mediaIds.', 'code': 324}]
    

Clearly I only have 1 media id, so the error makes no sense. I assume I'm
formatting the request incorrectly but I've tried a range of different formats
and none seem to work.

Any ideas as I'm out??

Thanks in advance.


Answer: Turns out the media_ids was not formatted as a string but instead a list of
strings, this differs from the Twitter API documentation and thus Tweepy must
format the request from the list before wrapping. Here is my code firstly for
multiple images:

    
    
    import tweepy
    from configparser import SafeConfigParser
    
    config = SafeConfigParser()
    config.read('/var/www/config.ini')
    
    CONSUMER_KEY = config.get('twitter', 'CONSUMER_KEY')
    CONSUMER_SECRET = config.get('twitter', 'CONSUMER_SECRET')
    ACCESS_KEY = config.get('twitter', 'ACCESS_KEY')
    ACCESS_SECRET = config.get('twitter', 'ACCESS_SECRET')
    
    auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
    auth.set_access_token(ACCESS_KEY, ACCESS_SECRET)
    api = tweepy.API(auth)
    
    file = open('/var/www/photo1.jpeg', 'rb')
    r1 = api.media_upload(filename='/var/www/photo1.jpeg', file=file)
    print(r1)
    print(r1.media_id_string)
    file = open('/var/www/photo2.jpeg', 'rb')
    r2 = api.media_upload(filename='/var/www/photo2.jpeg', file=file)
    print(r2)
    print(r2.media_id_string)
    media_ids = [r1.media_id_string, r2.media_id_string]
    print(media_ids)
    api.update_status(media_ids=media_ids, status="Test Tweet")
    

and then for a single image:

    
    
    import tweepy
    from configparser import SafeConfigParser
    
    config = SafeConfigParser()
    config.read('/var/www/config.ini')
    
    CONSUMER_KEY = config.get('twitter', 'CONSUMER_KEY')
    CONSUMER_SECRET = config.get('twitter', 'CONSUMER_SECRET')
    ACCESS_KEY = config.get('twitter', 'ACCESS_KEY')
    ACCESS_SECRET = config.get('twitter', 'ACCESS_SECRET')
    
    auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
    auth.set_access_token(ACCESS_KEY, ACCESS_SECRET)
    api = tweepy.API(auth)
    
    file = open('/var/www/photo1.jpeg', 'rb')
    r1 = api.media_upload(filename='/var/www/photo1.jpeg', file=file)
    print(r1)
    print(r1.media_id_string)
    file = open('/var/www/photo2.jpeg', 'rb')
    r2 = api.media_upload(filename='/var/www/photo2.jpeg', file=file)
    print(r2)
    print(r2.media_id_string)
    media_ids = [r1.media_id_string_ids]
    print(media_ids)
    api.update_status(media_ids=media_ids, status="Test Tweet")
    

