This document explains how to force storage errors for testing the user experience when S3 operations fail.
The storage module (storymap/storage.py) includes an error injection system controlled by the FORCE_STORAGE_ERROR environment variable. This allows you to selectively fail read operations, write operations, or both, to test how the application handles various failure scenarios.
FORCE_STORAGE_ERROR=error_type[:operation]
- error_type (required): Type of error to simulate
- operation (optional):
:read,:write, or omit for all operations
| Error Type | Description | User Message |
|---|---|---|
connection |
Simulates S3 connection failure | "Could not connect to document store" |
timeout |
Simulates request timeout | "Request timeout while accessing document store" |
permission |
Simulates permission denied | "Permission denied accessing document store" |
notfound |
Simulates document not found | "Document not found in store" |
corrupt |
Simulates corrupted/invalid data | "Document data is corrupted or invalid" |
These operations retrieve data from S3:
load_json- Load StoryMap dataget_contents- Get file contentsget_contents_as_string- Get file as stringlist_keys- List S3 keyslist_key_names- List key names
These operations modify data in S3:
save_json- Save StoryMap datasave_from_data- Save file from datasave_bytes_from_data- Save bytessave_from_url- Download and save from URLcopy_key- Copy S3 objectdelete_key- Delete single objectdelete_keys- Delete multiple objects
This lets you open/load StoryMaps normally but fails when trying to save:
-
Add to your
.envfile:FORCE_STORAGE_ERROR=connection:write
-
Recreate the app container to pick up the environment variable:
docker compose up -d app
-
Test: You can now load StoryMaps normally, but saves/uploads will fail
This lets you save data but fails when trying to load:
FORCE_STORAGE_ERROR=timeout:readThis fails both reads and writes:
FORCE_STORAGE_ERROR=connectionThe helper script provides usage information but you'll still need to manually edit .env and recreate the container:
# Show usage and examples
./scripts/test-storage-errors.sh
# To use:
# 1. Edit .env and add: FORCE_STORAGE_ERROR=connection:write
# 2. Run: docker compose up -d app
# To clear:
# 1. Remove FORCE_STORAGE_ERROR from .env
# 2. Run: docker compose up -d app-
Add to your
.envfile:FORCE_STORAGE_ERROR=connection:write
-
IMPORTANT: Recreate the app container to pick up the new environment variable:
docker compose up -d app
Note:
docker compose restart appwill NOT work because it doesn't reload environment variables from.env. You must usedocker compose up -d appto recreate the container. -
To clear, remove the line from
.envand recreate again:# Remove FORCE_STORAGE_ERROR from .env docker compose up -d app
Set the environment variable directly in docker-compose.yml:
services:
app:
environment:
FORCE_STORAGE_ERROR: timeout:writeThen recreate the container: docker compose up -d app
-
Choose an error type and operation:
connection:write- Test save failures while allowing loadsnotfound:read- Test load failures while allowing savesconnection- Test complete storage failure
-
Set the environment variable using one of the methods above
-
Recreate the app container to apply the change:
docker compose up -d app
Important: This preserves LocalStack data while picking up the new environment variable.
-
Perform storage operations in the application:
- Test reads: Load a StoryMap, list images
- Test writes: Save/update a StoryMap, upload an image, delete a StoryMap
-
Observe the error handling in the UI
-
Check the logs for detailed error messages:
docker compose logs -f app
Look for lines like:
[ERROR INJECTION] Forcing write error 'connection' on save_json()
When a StorageException is raised:
- API Response: JSON with
erroranderror_detailfields - HTTP Status: Usually 200 (errors are in JSON body)
- Logging: Error is logged to app container logs
- User Experience: Should see error message in the UI
Example API error response:
{
"error": "Could not connect to document store: Simulated connection error",
"error_detail": "FORCE_STORAGE_ERROR=connection:write - Simulated connection failure on write operation"
}These endpoints will fail with read:* errors:
GET /storymap/- Load StoryMap (callsload_json)GET /storymap/images/<id>- List images (callslist_key_names)GET /storymap/export/- Export StoryMap (callsget_contents_as_string,list_keys)
These endpoints will fail with write:* errors:
POST /storymap/save/- Save StoryMap (callssave_json)POST /storymap/update/<id>- Update StoryMap (callssave_json)POST /storymap/publish/<id>- Publish StoryMap (callssave_json)POST /storymap/image/upload/<id>- Upload image (callssave_from_data)POST /storymap/copy/- Copy StoryMap (callssave_json,copy_key)POST /storymap/delete/- Delete StoryMap (callsdelete_keys)
These endpoints use both reads and writes, so will fail with any error type:
POST /storymap/copy/- Reads source, writes destination
- Check container logs:
docker compose logs -f appto see[ERROR INJECTION]messages - Browser DevTools: Network tab to see API responses
- Test incrementally: Test one error type at a time
- Clear between tests: Remove
FORCE_STORAGE_ERRORand restart to return to normal operation
To return to normal operation:
- Remove
FORCE_STORAGE_ERRORfrom.envordocker-compose.yml - Recreate the app container:
docker compose up -d app - Verify normal operation
Note: LocalStack data will be preserved during this process.
- Error injection applies to all storage operations, not just specific functions
- The error is raised before any actual S3 operation occurs
- This is a development/testing feature only - should not be used in production
- Error messages are designed to be user-friendly while providing detail for debugging