Description
The NCAT API uploads files to cloud storage without specifying Content-Type headers across
all storage providers (S3-compatible and Google Cloud Storage). This causes upload failures
with Supabase Storage and prevents inline media viewing in browsers.
Environment
- NCAT Version:
stephengpope/no-code-architects-toolkit:latest
- Build Number: 206
- Python Version: 3.9.23
- Deployment: Docker
- Tested Storage Backends:
- Supabase Storage (S3-compatible) ❌ Fails with InvalidMimeType
- AWS S3 ⚠️ Defaults to application/octet-stream
- DigitalOcean Spaces ⚠️ Defaults to application/octet-stream
- Google Cloud Storage ⚠️ Auto-detects (unreliable)
Problem Details
Error from production logs:
ERROR:services.s3_toolkit:Error uploading file to S3: An error occurred (InvalidMimeType)
when calling the PutObject operation: mime type application/octet-stream is not supported
Failure Statistics (Oct 15-21, 2025):
- 42 unique job failures over 7 days
- 41 failures today alone (accelerating issue)
- Affected endpoints:
/v1/image/convert/video - 41 failures (98%)
/v1/media/download - 1 failure (2%)
User Impact:
- ❌ Supabase Storage rejects uploads entirely
- ❌ MP4 videos download instead of playing in browser
- ❌ MP3 audio files download instead of streaming
- ❌ Images download instead of displaying inline
Root Cause
1. S3-Compatible Provider (services/s3_toolkit.py)
def upload_to_s3(file_path, s3_url, access_key, secret_key, bucket_name, region):
# ...
client.upload_fileobj(data, bucket_name,
os.path.basename(file_path),
ExtraArgs={'ACL': 'public-read'}) # ❌ No ContentType
Problem: boto3 defaults to application/octet-stream when ContentType is not specified.
2. Google Cloud Storage Provider (services/gcp_toolkit.py)
def upload_to_gcs(file_path, bucket_name=GCP_BUCKET_NAME):
# ...
blob = bucket.blob(os.path.basename(file_path))
blob.upload_from_filename(file_path) # ❌ No content_type parameter
Problem: GCP auto-detects MIME type, but this is unreliable.
Proposed Solution
Use Python's built-in mimetypes library to auto-detect Content-Type from file extensions:
Fix for services/s3_toolkit.py
import mimetypes
def upload_to_s3(file_path, s3_url, access_key, secret_key, bucket_name, region):
session = boto3.Session(
aws_access_key_id=access_key,
aws_secret_access_key=secret_key,
region_name=region
)
client = session.client('s3', endpoint_url=s3_url)
try:
# Auto-detect MIME type from file extension
content_type, _ = mimetypes.guess_type(file_path)
if not content_type:
content_type = 'application/octet-stream'
logger.info(f"Uploading {os.path.basename(file_path)} with Content-Type:
{content_type}")
with open(file_path, 'rb') as data:
client.upload_fileobj(data, bucket_name,
os.path.basename(file_path),
ExtraArgs={
'ACL': 'public-read',
'ContentType': content_type # ✅ Add this
})
encoded_filename = quote(os.path.basename(file_path))
file_url = f"{s3_url}/{bucket_name}/{encoded_filename}"
return file_url
except Exception as e:
logger.error(f"Error uploading file to S3: {e}")
raise
Fix for services/gcp_toolkit.py
import mimetypes
def upload_to_gcs(file_path, bucket_name=GCP_BUCKET_NAME):
# ... existing validation ...
# Auto-detect MIME type from file extension
content_type, _ = mimetypes.guess_type(file_path)
if not content_type:
content_type = 'application/octet-stream'
logger.info(f"Uploading {os.path.basename(file_path)} with Content-Type: {content_type}")
bucket = gcs_client.bucket(bucket_name)
blob = bucket.blob(os.path.basename(file_path))
blob.upload_from_filename(file_path, content_type=content_type) # ✅ Add content_type
# ... rest of function ...
Benefits
✅ Eliminates InvalidMimeType errors with Supabase Storage✅ Enables inline viewing of media
files in browsers✅ Consistent behavior across all storage backends✅ Zero breaking changes -
fully backwards compatible✅ No new dependencies - uses Python standard library
Additional Notes
I'm happy to submit a PR with both fixes if this approach is acceptable. This issue affects all
users regardless of which storage backend they choose.
Description
The NCAT API uploads files to cloud storage without specifying Content-Type headers across
all storage providers (S3-compatible and Google Cloud Storage). This causes upload failures
with Supabase Storage and prevents inline media viewing in browsers.
Environment
stephengpope/no-code-architects-toolkit:latestProblem Details
Error from production logs:
ERROR:services.s3_toolkit:Error uploading file to S3: An error occurred (InvalidMimeType)
when calling the PutObject operation: mime type application/octet-stream is not supported
Failure Statistics (Oct 15-21, 2025):
/v1/image/convert/video- 41 failures (98%)/v1/media/download- 1 failure (2%)User Impact:
Root Cause
1. S3-Compatible Provider (
services/s3_toolkit.py)