Curl silently fails to upload file to downloads with HTTP/2 401 in the logs
Asked by Denis Baltor:

I'm trying to upload a file to my repo's downloads section from my pipeline using curl.

The step doesn't fail but the file is NOT uploaded. We can read **HTTP/2 401** in the logs (line 70):  

    + curl -v -X POST -u "${BITBUCKET_USERNAME}:${BITBUCKET_APP_PASSWORD}" "https://api.bitbucket.org/2.0/repositories/$%7BBITBUCKET_REPO_OWNER%7D/$%7BBITBUCKET_REPO_SLUG%7D/downloads" -F files="@dependency-check.tar"
    2 Note: Unnecessary use of -X or --request, POST is already inferred.

    3 % Total % Received % Xferd Average Speed Time Time Time Current

    4 Dload Upload Total Spent Left Speed 

    5

    6 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 18.205.93.6:443... 

    7 * Connected to http://api.bitbucket.org/ (18.205.93.6) port 443

    8 * ALPN: curl offers h2,http/1.1 

    9 } [5 bytes data]

    10 * TLSv1.3 (OUT), TLS handshake, Client hello (1):

    11 } [512 bytes data]

    12 * CAfile: /etc/pki/tls/certs/ca-bundle.crt

    13 * CApath: none

    14 { [5 bytes data]

    15 * TLSv1.3 (IN), TLS handshake, Server hello (2):

    16 { [88 bytes data]

    17 * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):

    18 } [1 bytes data]

    19 * TLSv1.3 (OUT), TLS handshake, Client hello (1):

    20 } [512 bytes data]

    21 * TLSv1.3 (IN), TLS handshake, Server hello (2):

    22 { [155 bytes data] 

    23 * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):

    24 { [15 bytes data]

    25 * TLSv1.3 (IN), TLS handshake, Certificate (11):

    26 { [2772 bytes data]

    27 * TLSv1.3 (IN), TLS handshake, CERT verify (15):

    28 { [78 bytes data]

    29 * TLSv1.3 (IN), TLS handshake, Finished (20):

    30 { [36 bytes data]

    31 * TLSv1.3 (OUT), TLS handshake, Finished (20):

    32 } [36 bytes data] 

    33 * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256

    34 * ALPN: server accepted h2

    35 * Server certificate:

    36 * subject: C=US; ST=California; L=San Francisco; O=Atlassian US, Inc.; CN=*.bitbucket.org

    37 * start date: Apr 28 00:00:00 2023 GMT

    38 * expire date: Mar 28 23:59:59 2024 GMT

    39 * subjectAltName: host "http://api.bitbucket.org/" matched cert's "*.bitbucket.org"

    40 * issuer: C=US; O=DigiCert Inc; http://ou%3Dwww.digicert.com/; CN=DigiCert SHA2 High Assurance Server CA

    41 * SSL certificate verify ok.

    42 } [5 bytes data]

    43 * using HTTP/2

    44 * Server auth using Basic with user '<OMMITED>'

    45 * [HTTP/2] [1] OPENED stream for https://api.bitbucket.org/2.0/repositories/evolate/elevate-insights/downloads46 * [HTTP/2] [1] [:method: POST]

    47 * [HTTP/2] [1] [:scheme: https]

    48 * [HTTP/2] [1] [:authority: http://api.bitbucket.org/]

    49 * [HTTP/2] [1] [:path: /2.0/repositories/<OMMITED>/<OMMITED>/downloads]

    50 * [HTTP/2] [1] [authorization: Basic <OMMITED>]
     
    51 * [HTTP/2] [1] [user-agent: curl/8.3.0]

    52 * [HTTP/2] [1] [accept: */*]

    53 * [HTTP/2] [1] [content-length: 200315093]

    54* [HTTP/2] [1] [content-type: multipart/form-data; boundary=------------------------40685d70a281abee]

    55 } [5 bytes data]

    56 > POST /2.0/repositories/<OMMITED>/<OMMITED>/downloads HTTP/2

    57 > Host: http://api.bitbucket.org/58 > Authorization: Basic <OMMITED>

    59 > User-Agent: curl/8.3.0

    60 > Accept: */*

    61 > Content-Length: 200315093

    62 > Content-Type: multipart/form-data; boundary=------------------------40685d70a281abee

    63 > 

    64 } [5 bytes data]

    65 * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):

    66 { [202 bytes data]

    67

    68 51 191M 0 0 51 97.8M 0 231M --:--:-- --:--:-- --:--:-- 231M* We are completely uploaded and fine

    69 { [5 bytes data]
     
    70 < HTTP/2 401 

    71 < server: envoy

    72 * Authentication problem. Ignoring this.

    73 < www-authenticate: Basic realm="http://bitbucket.org/ HTTP"

    74 < vary: Origin

    75 < cache-control: max-age=0, no-cache, no-store, must-revalidate

    76< content-type: text/plain

    77< x-b3-traceid: 213298583d24461f

    78< x-usage-output-ops: 0

    79< x-dc-location: Micros-3

    80< strict-transport-security: max-age=31536000; includeSubDomains; preload

    81< date: Thu, 02 Nov 2023 09:45:10 GMT

    82< x-request-id: 213298583d24461f

    83< x-usage-user-time: 0.010569

    84< x-usage-system-time: 0.000000

    85< x-served-by: 1734b7da7b86

    86< expires: Thu, 02 Nov 2023 09:45:10 GMT

    87< x-xss-protection: 1; mode=block

    88< x-envoy-upstream-service-time: 49

    89< x-b3-spanid: 8de8f4bddac92b22

    90< x-static-version: 0a88acc2851f

    91< x-content-type-options: nosniff

    92< x-render-time: 0.008195877075195312

    93< x-trace-id: 213298583d24461f

    94< x-usage-input-ops: 0

    95< x-version: 0a88acc2851f

    96< x-request-count: 2690

    97< x-frame-options: SAMEORIGIN

    98< content-length: 0

    99< 

    100

    101 100 191M 0 0 100 191M 0 121M 0:00:01 0:00:01 --:--:-- 121M{ [0 bytes data]

    102


    103 100 191M 0 0 100 191M 0 121M 0:00:01 0:00:01 --:--:-- 121M

    104 * Connection #0 to host http://api.bitbucket.org/ left intact

<br />

The same command works just fine from a local container I built following [this guidance](https://confluence.atlassian.com/bbkb/debug-pipelines-locally-with-docker-1167698072.html). In this case, the logs reads like below:

    * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
    * We are completely uploaded and fine
    < HTTP/2 201
    < server: envoy?


Answers:
author: Theodora Boudale
body: Hi Denis and welcome to the community!

A 401 error indicates an issue with the credentials used for authentication.

If you are using the credentials of your own account, please ensure the following:

* BITBUCKET_USERNAME should be the username of your Bitbucket account and it can be found here <https://bitbucket.org/account/settings/>. The call won't work if you use your email address or the label of the app password.
* The app password needs to have at least **Repositories - Write** permission for the call to succeed. If you don't remember the app password's permissions, you can generate a new one via <https://bitbucket.org/account/settings/app-passwords/> and replace the value of BITBUCKET_APP_PASSWORD in **Repository settings**.
* The Bitbucket account whose credentials you use for authentication needs to have at least write access to the repo you want to upload the file.

You could also use a repository access token instead of username and app password (so you don't store an account's credentials in the variables). The repository access token can be generated from **Repository settings \> Access tokens** of the repo you are uploading to (if you are not an admin, you can ask an admin to generate an access token with **Repositories - Write** permission).

You can then use a call as follows, where **access_token** is a repository variable in the repo where the build runs and it holds the value of the repository access token:

```
curl -v -X POST "https://api.bitbucket.org/2.0/repositories/${BITBUCKET_REPO_OWNER}/${BITBUCKET_REPO_SLUG}/downloads" -F files="@dependency-check.tar" --header "Authorization:Bearer ${access_token}"
```

Kind regards,  
Theodora

comments: author: Denis Baltor
body: Hi Theodora,  
Thank you very much for reaching out. I had done all the app password setup you mentioned above but did it again anyway. I seem to have messed the password up when copying it into the pipeline secret. It's working now.  

However, I-ll switch to the access token approach. You advice was much appreciated!  

Kind regards  
Denis


author: Theodora Boudale
body: Hi Denis,

Thank you for the update and you are very welcome!

Please feel free to reach out if you ever need anything else!

Kind regards,  
Theodora


Tags: bitbucket-cloud

cloud