Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Rest API: posting a file on bitbucket loses its execution mode

laurens_brock
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
December 9, 2025

Hi,

 

I'm trying to alter an existing file on bitbucket using this rest call:
https://developer.atlassian.com/cloud/bitbucket/rest/api-group-source/#api-repositories-workspace-repo-slug-src-post

 

But whenever I change a file which has a +x modifier, it loses it after I run the post command.  The file change however does still go through. So I always get a 201 response.

So after the change, I checkout the branch to verify and I get the following result:
diff --git a/ci/build.sh b/ci/build.sh
old mode 100755
new mode 100644

I tried it with and without Content-Disposition, but it neither seem to work.

This is my last attempt:

```

def upload_files_to_repo(
    repo_slug: str, branch_name: str, file_contents: dict, commit_message: str
) -> bool:

    data = {"branch": branch_name, "message": commit_message}

    headers = get_header()
    headers.update({"Content-Disposition": 'attachment; filename="ci/build.sh"; x-attributes:"executable"'})
    url = f"https://api.bitbucket.org/2.0/repositories/{WORKSPACE_SLUG}/{repo_slug}/src"
    files = {file_path: file_content for file_path, file_content in file_contents.items()}

    response = requests.post(url, headers=headers, files=files, data=data)

```

Also doing something along the lines of this doesn't seem to work either:
```

url = f"https://api.bitbucket.org/2.0/repositories/{WORKSPACE}/{REPO_SLUG}/src"

m = MultipartEncoder(
fields={
"message": "Add shutdown script + symlink",
"branch": BRANCH,

# destination paths in the repo:
"bin/shutdown.sh": part(
"bin/shutdown.sh",
"shutdown.sh",
b"#!/bin/sh\nhalt\n",
"executable",
),
"README.txt": part(
"README.txt",
"README.txt",
b"README\n", # symlink target path :contentReference[oaicite:3]{index=3}
"link",
),
}
)

resp = requests.post(
url,
data=m,
headers={"Authorization": f"Bearer {ACCESS_TOKEN}", "Content-Type": m.content_type},
timeout=30,
)

```

 

Any help with some concrete examples would be appreciated.

 

1 answer

1 vote
Sunny Ape
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Champions.
December 19, 2025

Hello @laurens_brock 

Try asking your question to an AI like ChatGPT. I did and it gave me a very long-winded explanation that you must set the mode on the multipart field, not in headers.

ChatGPT said:

Key point (short answer)

Content-Disposition headers and custom attributes are ignored for file permissions.
The executable bit (+x, mode 100755) is Git metadata, and Bitbucket Cloud will default files uploaded via src to 100644 unless you explicitly set the mode in the multipart form field itself.

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
TAGS
AUG Leaders

Atlassian Community Events