Solutions to common errors and issues when uploading to Confluence.
- Critical Issues
- Markdown Conversion Issues
- API and Authentication Issues
- File and Path Issues
- Version and Update Issues
- Performance Issues
- Debugging Techniques
- Prevention Checklist
Symptom:
Error: Request payload too large
Error: MCP request failed: content exceeds maximum size
Cause: MCP tools have size limits and cannot handle large documents (typically > 10-20KB).
Solution: DO NOT USE MCP FOR CONFLUENCE PAGE UPLOADS!
Use REST API instead:
# ❌ Don't use MCP
# mcp__atlassian-evinova__confluence_update_page
# ✅ Use REST API via upload script
python3 ~/.claude/skills/confluence/scripts/upload_confluence_v2.py \
document.md --id 780369923Prevention:
- Add to project memory: "DO NOT USE MCP FOR CONFLUENCE UPLOADS"
- Always use
upload_confluence_v2.pyscript for page uploads - MCP is fine for reading pages, but not for uploading content
Symptom: Images show as escaped HTML on the Confluence page:
<ac:image><ri:attachment ri:filename="diagram.png"/></ac:image>
Cause: Raw Confluence XML was placed in markdown, and md2cf HTML-escaped it.
Root Cause Explanation:
- You put:
<ac:image><ri:attachment ri:filename="diagram.png"/></ac:image>in markdown - md2cf treats this as plain text (not markdown)
- md2cf HTML-escapes special characters:
<→<,>→> - Confluence receives escaped text and displays it literally
Solution: Use markdown image syntax instead:
# ❌ Wrong - Don't put raw XML in markdown
<ac:image><ri:attachment ri:filename="diagram.png"/></ac:image>
# ✅ Correct - Use markdown syntax
How md2cf Handles This:

↓ md2cf converts to ↓
<ac:image ac:alt="Diagram">
<ri:attachment ri:filename="diagram.png"/>
</ac:image>Prevention:
- Never put raw Confluence XML in markdown files
- Always use standard markdown image syntax:
 - Let md2cf handle conversion to storage format
Symptom: Upload script crashes with Python error:
TypeError: string indices must be integers, not 'str'
File "upload_confluence.py", line 176, in upload_to_confluence
'version': result['version']['number']Cause:
- Old
upload_confluence.pyscript has incorrect error handling - API response structure is different than expected
- Often happens when
MermaidConfluenceRendereris used incorrectly
Solution:
Use the improved upload_confluence_v2.py script:
# ✅ Use v2 script with better error handling
python3 ~/.claude/skills/confluence/scripts/upload_confluence_v2.py \
document.md --id 780369923What v2 Fixes:
- Uses base
ConfluenceRenderer(notMermaidConfluenceRenderer) - Better error handling for API responses
- Proper handling of version numbers
- Clearer error messages
Symptom:
- Page uploads successfully
- Content appears correctly
- Images show as gray placeholder icons or "missing attachment" icons
Cause: Image attachments were not uploaded, only page content was updated.
Solution:
Check 1: Verify attachments were uploaded
# Make sure upload script includes attachment upload
for image_path in attachments:
confluence.attach_file(
filename=image_path,
page_id=page_id,
...
)Check 2: Verify image files exist
# List all images referenced in markdown
grep -o '!\[.*\](.*\.png)' document.md
# Verify each file exists
ls -lh ./path/to/images/Check 3: Verify image paths are correct
# In your markdown, paths must be relative or absolute
 # ✅ Relative path
 # ✅ Absolute path
 # ⚠️ Must be in same directoryPrevention:
- Always use
upload_confluence_v2.pywhich handles attachments correctly - Verify all image files exist before uploading
- Check script output for "Uploading N attachments..." message
Symptom:
attachments = [] # Empty list, but markdown has imagesCauses:
-
Incorrect Image Syntax:
# ❌ Wrong syntax <img src="diagram.png"> # HTML, not markdown [Diagram](diagram.png) # Link, not image (missing !) # ✅ Correct syntax 
-
Using MermaidConfluenceRenderer:
# ❌ Breaks regular images renderer = MermaidConfluenceRenderer() # ✅ Use base renderer renderer = ConfluenceRenderer()
Solution:
- Check markdown image syntax:
 - Use base
ConfluenceRenderer - Verify paths are correct
Symptom:
- Mermaid code blocks appear as regular code, not diagrams
Cause: You're using Mermaid code blocks in markdown, but Confluence doesn't support Mermaid natively.
Solution: Convert Mermaid to PNG/SVG FIRST, then reference as regular image:
# Option 1: Use design-doc-mermaid skill
Skill: "design-doc-mermaid"
# Follow prompts to convert diagrams
# Option 2: Manual conversion
mmdc -i architecture.mmd -o architecture.png -b transparent
# Then in markdown:
Why Not Use MermaidConfluenceRenderer?
- It overwrites parent's
attachmentsattribute - Breaks regular markdown image handling
- Creates incompatible attachment list format
Better Approach:
- Convert diagrams to images separately
- Use base
ConfluenceRenderer - Reference images with markdown syntax
Symptom:
- PlantUML code appears as text, not diagrams
Solution: Same as Mermaid - convert to images first:
# Use plantuml skill
Skill: "plantuml"
# Follow prompts
# Or manually:
plantuml diagram.puml -tpng
# Reference in markdown:
Symptom:
ERROR: 401 Unauthorized
ERROR: Authentication failed
Causes:
-
Missing or Invalid Credentials:
.envfile not found- API token expired
- Wrong username/password
-
Wrong .env File Path:
# ❌ Default .env not found python3 upload_confluence_v2.py document.md --id 123 # ✅ Specify correct path python3 upload_confluence_v2.py document.md --id 123 \ --env-file /Users/you/clients/evinova/.env.jira
Solution:
Check 1: Verify credentials file exists
ls -la /Users/you/clients/evinova/.env.jiraCheck 2: Verify credentials format
# .env.jira should contain:
CONFLUENCE_USERNAME=your.email@company.com
CONFLUENCE_API_TOKEN=your_api_token_here
CONFLUENCE_BASE_URL=https://yourcompany.atlassian.net/wikiCheck 3: Test credentials
# Use confluence_auth.py to test
python3 -c "
from confluence_auth import get_confluence_client
client = get_confluence_client(env_file='/path/to/.env.jira')
print('✅ Authentication successful!')
"Generate New API Token:
- Go to: https://id.atlassian.com/manage-profile/security/api-tokens
- Click "Create API token"
- Copy token and update
.env.jirafile
Symptom:
ERROR: Failed to fetch current version for page 123456: Page not found
Causes:
- Page ID is incorrect
- Page was deleted
- No permission to access page
Solution:
Find Correct Page ID:
# From Confluence URL:
https://company.atlassian.net/wiki/spaces/TEAM/pages/780369923/Page+Title
^^^^^^^^^ This is the page ID
Verify Page Exists:
# Try reading the page first
python3 -c "
from confluence_auth import get_confluence_client
client = get_confluence_client()
page = client.get_page_by_id('780369923')
print(f'Page found: {page[\"title\"]}')
"Symptom:
❌ File not found: ./diagrams/architecture.png
Causes:
- Image file doesn't exist at specified path
- Relative path is incorrect
- Working directory is wrong
Solution:
Check 1: Verify file exists
# From directory where markdown file is located
ls -lh ./diagrams/architecture.pngCheck 2: Use absolute paths
# Instead of relative:

# Use absolute:
Check 3: Verify working directory
# Run upload script from same directory as markdown file
cd /path/to/markdown/directory
python3 ~/.claude/skills/confluence/scripts/upload_confluence_v2.py document.md --id 123Symptom:
ERROR: Version conflict - page has been updated since last read
Cause: Someone else updated the page while you were preparing your update.
Solution:
Option 1: Retry (script will fetch latest version)
# Simply run again - script auto-fetches current version
python3 upload_confluence_v2.py document.md --id 780369923Option 2: Manual version check
# Get current version before updating
page_info = confluence.get_page_by_id(page_id, expand='version')
current_version = page_info['version']['number']
print(f"Current version: {current_version}")Symptom:
- Upload takes > 30 seconds
- Script appears to hang
Causes:
- Large images: PNG files > 1MB each
- Many images: > 20 images to upload
- Slow network: Connection to Confluence is slow
Solution:
Optimize Images:
# Compress PNG files
pngquant --quality=70-85 diagram.png -o diagram-optimized.png
# Convert to SVG for diagrams (usually smaller)
mmdc -i diagram.mmd -o diagram.svg -b transparent
# Resize large screenshots
convert screenshot.png -resize 1920x1080 screenshot-resized.pngSkip Re-uploading Existing Attachments:
# v2 script skips by default
python3 upload_confluence_v2.py document.md --id 780369923
# Force re-upload if needed
python3 upload_confluence_v2.py document.md --id 780369923 --force-reuploadPreview what will be uploaded without making changes:
python3 upload_confluence_v2.py document.md --id 780369923 --dry-runOutput Shows:
- Mode (CREATE or UPDATE)
- Title
- Page ID
- Attachments list with file existence check
- Content preview (first 500 chars)
from md2cf.confluence_renderer import ConfluenceRenderer
import mistune
with open('document.md') as f:
markdown = f.read()
renderer = ConfluenceRenderer()
parser = mistune.Markdown(renderer=renderer)
html = parser(markdown)
print(f"Found {len(renderer.attachments)} images:")
for att in renderer.attachments:
print(f" - {att}")# Save storage format to file for inspection
with open('storage_output.html', 'w') as f:
f.write(storage_html)
print("Storage format saved to: storage_output.html")from confluence_auth import get_confluence_client
# Test connection
client = get_confluence_client(env_file='/path/to/.env.jira')
print(f"✅ Connected to: {client.url}")
# Test page access
page = client.get_page_by_id('780369923')
print(f"✅ Can access page: {page['title']}")
print(f" Current version: {page['version']['number']}")Before uploading to Confluence, verify:
- Using
upload_confluence_v2.py(not MCP, not old v1 script) - All images converted to PNG/SVG (not Mermaid/PlantUML code blocks)
- Using markdown image syntax:
 - No raw Confluence XML in markdown
- All image files exist at specified paths
- Credentials file path is correct
- Page ID is correct (from Confluence URL)
- Dry-run mode tested first (
--dry-run)
Documentation References:
Related Skills:
design-doc-mermaid- Mermaid diagram conversionplantuml- PlantUML diagram conversion
Confluence Resources: