Hi Team,
As of now, Workflow Studio does not support direct duplication of a project from the UI. If you’re trying to import a project and receive the error:
“Project with tag 1.0.0 already imported.”
…it’s because the system identifies the project based on its internal projectId
, and importing a project with the same ID is not allowed.
To help with this, you can use the following custom script that will clone your existing exported project zip, generate a new unique projectId
, and allow you to re-import it as a separate project for experimentation—while retaining the original.
import zipfile
import os
import shutil
import uuid
import json
import tempfile
import sys
def update_project_zip(zip_path: str, new_project_name: str, project_description: str) -> str:
zip_dir = os.path.dirname(zip_path)
sanitized_name = new_project_name.replace(" ", "_")
output_zip_path = os.path.join(zip_dir, f"{sanitized_name}.zip")
temp_dir = tempfile.mkdtemp()
extracted_folder = os.path.join(temp_dir, "extracted")
os.makedirs(extracted_folder, exist_ok=True)
# Step 1: Unzip the input zip file
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
zip_ref.extractall(extracted_folder)
# Step 2: Load project.json and get projectId
project_json_path = None
for root, _, files in os.walk(extracted_folder):
for file in files:
if file == "project.json":
project_json_path = os.path.join(root, file)
break
if not project_json_path:
raise FileNotFoundError("project.json not found in the zip archive.")
with open(project_json_path, "r") as f:
project_data = json.load(f)
if "project" not in project_data or "projectId" not in project_data["project"]:
raise KeyError("projectId not found inside the 'project' object of project.json.")
old_project_id = project_data["project"]["projectId"]
new_project_id = str(uuid.uuid4())
# Step 3: Replace projectId in all files
for root, _, files in os.walk(extracted_folder):
for file in files:
file_path = os.path.join(root, file)
with open(file_path, "r", encoding="utf-8") as f:
content = f.read()
content = content.replace(old_project_id, new_project_id)
with open(file_path, "w", encoding="utf-8") as f:
f.write(content)
# Step 4: Update project.json
project_data["project"]["projectId"] = new_project_id
project_data["project"]["name"] = new_project_name
project_data["project"]["description"] = project_description
project_data["project"]["enquiry"] = False
with open(project_json_path, "w") as f:
json.dump(project_data, f, indent=2)
# Step 5: Create a new zip file in same location as original
with zipfile.ZipFile(output_zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
for root, _, files in os.walk(extracted_folder):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, extracted_folder)
zipf.write(file_path, arcname)
shutil.rmtree(temp_dir)
return output_zip_path
if __name__ == "__main__":
if len(sys.argv) == 4:
project_name = sys.argv[1]
project_description = sys.argv[2]
zip_path = sys.argv[3]
else:
project_name = input("Enter new project name: ").strip()
project_description = input("Enter project description: ").strip()
zip_path = input("Enter path to the project zip file: ").strip()
try:
output = update_project_zip(zip_path, project_name, project_description)
print(f"✅ Updated project zip created at: {output}")
except Exception as e:
print(f"❌ Error: {e}")
How to Use:
You can run the script in two ways:
1. Using Command Line Arguments:
python duplicate_project.py "New Project Name" "Project description here" "/path/to/original_project.zip"
2. Interactive Mode:
Just run the script without arguments, and it will prompt you to enter:
- New project name
- Project description
- Path to the original project zip
Let me know if you face any issues running the script. Hope this helps you continue working without affecting your original project.
Regards,
Shamnad KS