Common Errors
This document provides solutions for the most frequently encountered Fluree errors.
LEDGER_NOT_FOUND
{
"error": "NotFound",
"message": "Ledger not found: mydb:main",
"code": "LEDGER_NOT_FOUND"
}
Causes
- Ledger doesn't exist
- Typo in ledger name
- Wrong branch name
- Nameservice not initialized
Solutions
Check ledger exists:
curl http://localhost:8090/v1/fluree/ledgers
Create ledger:
curl -X POST "http://localhost:8090/v1/fluree/create" \
-H "Content-Type: application/json" \
-d '{"ledger": "mydb:main"}'
Verify spelling:
- Check for typos in ledger name
- Verify branch name (default is
main) - Check case sensitivity
PARSE_ERROR
{
"error": "ParseError",
"message": "Invalid JSON-LD: unexpected token at line 5",
"code": "PARSE_ERROR",
"details": {
"line": 5,
"column": 12
}
}
Causes
- Invalid JSON syntax
- Invalid JSON-LD structure
- Invalid SPARQL syntax
- Missing required fields
Solutions
Validate JSON:
# Use jq to validate
cat query.json | jq .
Check JSON-LD:
- Validate @context format
- Check @id and @type values
- Verify array vs object usage
Check SPARQL:
- Validate syntax online
- Check PREFIX declarations
- Verify quote matching
Common JSON Mistakes:
// Bad: trailing comma
{
"select": ["?name"],
"where": [...],
}
// Good: no trailing comma
{
"select": ["?name"],
"where": [...]
}
INVALID_IRI
{
"error": "ValidationError",
"message": "Invalid IRI: not a valid URI",
"code": "INVALID_IRI",
"details": {
"iri": "not a uri"
}
}
Causes
- Malformed IRI
- Missing namespace prefix
- Invalid characters
- Spaces in IRI
Solutions
Use valid IRIs:
// Good
{"@id": "http://example.org/alice"}
{"@id": "ex:alice"}
// Bad
{"@id": "not a uri"}
{"@id": "alice"} // Missing namespace
{"@id": "ex:alice smith"} // Space
Define namespace:
{
"@context": {
"ex": "http://example.org/ns/"
},
"@graph": [
{"@id": "ex:alice"} // Now valid
]
}
URL encode spaces:
{"@id": "ex:alice%20smith"}
UNRESOLVED_COMPACT_IRI
Unresolved compact IRI 'ex:Person': prefix 'ex' is not defined in @context.
If this is intended as an absolute IRI, use a full form (e.g. http://...)
or add the prefix to @context.
This error fires from the JSON-LD strict compact-IRI guard. A value that looks like a compact IRI (prefix:suffix) appeared in an IRI position, but prefix is not defined in @context and is not a recognised absolute scheme.
Causes
- Forgotten
@contexton a query or transaction - Misspelled or missing prefix in
@context - Intentionally using a bare
prefix:suffixstring as an opaque identifier
Solutions
Add the missing prefix to @context (most common fix):
{
"@context": {"ex": "http://example.org/ns/"},
"@graph": [{"@id": "ex:alice", "ex:name": "Alice"}]
}
Use a full absolute IRI instead of the compact form:
{
"@graph": [
{"@id": "http://example.org/ns/alice", "http://example.org/ns/name": "Alice"}
]
}
Opt out of the guard for legacy data where bare prefix:suffix strings are intentional:
{
"@context": {"ex": "http://example.org/ns/"},
"opts": {"strictCompactIri": false},
"@graph": [{"@id": "legacy:alice", "ex:name": "Alice"}]
}
The opt-out applies to both queries and transactions. See IRIs and @context — Strict Compact-IRI Guard for the full policy.
QUERY_TIMEOUT
{
"error": "Timeout",
"message": "Query execution exceeded timeout of 30000ms",
"code": "QUERY_TIMEOUT",
"details": {
"timeout_ms": 30000,
"elapsed_ms": 31245
}
}
Causes
- Complex query
- Large result set
- High indexing lag
- Insufficient resources
Solutions
Add LIMIT:
{
"select": ["?name"],
"where": [...],
"limit": 100 // Add limit
}
Add filters:
{
"where": [...],
"filter": "?age > 18" // Reduce result set
}
Check indexing lag:
curl http://localhost:8090/v1/fluree/info/mydb:main
# If (t - index.t) is large, wait for indexing (or reduce write rate)
Simplify query:
- Break into smaller queries
- Remove unnecessary joins
- Use more specific patterns
Increase timeout:
curl -X POST http://localhost:8090/v1/fluree/query \
-H "X-Fluree-Timeout: 60000" \
-d '{...}'
POLICY_DENIED
{
"error": "Forbidden",
"message": "Policy denies access to ledger mydb:main",
"code": "POLICY_DENIED",
"details": {
"subject": "did:key:z6Mkh...",
"action": "query",
"ledger": "mydb:main"
}
}
Causes
- No permission for operation
- Missing authentication
- Policy misconfiguration
- Wrong DID/identity
Solutions
Check authentication:
# Are you sending credentials?
curl -H "Authorization: Bearer token" ...
Verify policy:
# Query policies
SELECT ?policy ?subject ?action ?allow
WHERE {
?policy a f:Policy .
?policy f:subject ?subject .
?policy f:action ?action .
?policy f:allow ?allow .
}
Test with policy trace:
curl -X POST http://localhost:8090/v1/fluree/query \
-H "X-Fluree-Policy-Trace: true" \
-d '{...}'
Check DID:
- Verify DID in signed request
- Check DID is registered
- Verify public key
TYPE_ERROR
{
"error": "TypeError",
"message": "Expected integer, got string",
"code": "TYPE_ERROR",
"details": {
"expected": "xsd:integer",
"actual": "xsd:string",
"value": "not a number"
}
}
Causes
- Wrong datatype
- Type mismatch in comparison
- Invalid type conversion
Solutions
Use correct types:
// Good
{"ex:age": 30}
{"ex:age": {"@value": "30", "@type": "xsd:integer"}}
// Bad
{"ex:age": "30"} // String, not integer
Check type constraints:
- Verify expected types
- Use explicit @type
- Validate before submitting
PAYLOAD_TOO_LARGE
{
"error": "PayloadTooLarge",
"message": "Transaction exceeds maximum size of 10485760 bytes",
"code": "PAYLOAD_TOO_LARGE",
"details": {
"max_size": 10485760,
"actual_size": 15000000
}
}
Causes
- Transaction too large
- Query result too large
- Large embedded data
Solutions
Batch large transactions:
const batchSize = 1000;
for (let i = 0; i < entities.length; i += batchSize) {
const batch = entities.slice(i, i + batchSize);
await transact({"@graph": batch});
}
Use LIMIT for queries:
{
"select": ["?name"],
"where": [...],
"limit": 1000 // Paginate
}
Increase limits (if appropriate):
./fluree-db-server --max-transaction-size 20971520
STORAGE_ERROR
{
"error": "StorageError",
"message": "Cannot write to storage",
"code": "STORAGE_ERROR"
}
Causes
- Disk full (file storage)
- Permission errors
- AWS connectivity (AWS storage)
- Storage backend down
Solutions
File Storage:
# Check disk space
df -h /var/lib/fluree
# Check permissions
ls -la /var/lib/fluree
sudo chown -R fluree:fluree /var/lib/fluree
AWS Storage:
# Check AWS credentials
aws sts get-caller-identity
# Check S3 access
aws s3 ls s3://fluree-prod-data/
# Check DynamoDB
aws dynamodb describe-table --table-name fluree-nameservice
HIGH_INDEXING_LAG
Not an error, but a warning condition.
Symptoms
curl http://localhost:8090/v1/fluree/info/mydb:main
{
"commit_t": 150,
"index_t": 0
}
Causes
- Transaction rate exceeds indexing capacity
- Large transactions
- Insufficient resources
- Storage bottleneck
Solutions
Tune indexing:
fluree-server \
--indexing-enabled \
--reindex-min-bytes 100000 \
--reindex-max-bytes 1000000
Reduce transaction rate:
// Add delay between transactions
await transact(data);
await sleep(100);
Wait for catchup:
async function waitForIndexing() {
while (true) {
const status = await getStatus();
const lag = status.commit_t - status.index_t;
if (lag < 10) break;
await sleep(1000);
}
}
Add resources:
- More CPU
- More memory
- Faster disk
CONCURRENT_MODIFICATION
{
"error": "Conflict",
"message": "Concurrent modification detected",
"code": "CONCURRENT_MODIFICATION"
}
Causes
- Multiple processes updating same entity
- Nameservice contention
- Race condition
Solutions
Implement retry:
async function transactWithRetry(data, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await transact(data);
} catch (err) {
if (err.code === 'CONCURRENT_MODIFICATION' && i < maxRetries - 1) {
await sleep(Math.pow(2, i) * 100);
continue;
}
throw err;
}
}
}
Use upsert for retry-friendly transactions:
# Upsert is more retry-friendly for idempotent entity transactions
POST /upsert?ledger=mydb:main
SIGNATURE_VERIFICATION_FAILED
{
"error": "SignatureVerificationFailed",
"message": "Invalid signature",
"code": "INVALID_SIGNATURE"
}
Causes
- Wrong private key
- Payload modified after signing
- Incorrect algorithm
- Key not registered
Solutions
Verify signing process:
// Ensure payload not modified
const payload = JSON.stringify(transaction);
const jws = await sign(payload, privateKey);
// Don't modify payload after signing
Check algorithm:
{
"alg": "EdDSA", // Must match key type
"kid": "did:key:z6Mkh..."
}
Verify public-key material: standalone server signed requests use the key
material embedded in supported JWS/JWT headers (or configured OIDC JWKS). There
is no /admin/keys registration endpoint.
Memory Issues
Symptoms
- Out of memory errors
- Server crashes
- Slow performance
- Swap usage
Solutions
Check memory:
curl http://localhost:8090/v1/fluree/stats
Reduce memory usage:
# See docs/operations/configuration.md for current memory-related flags.
# In general: reduce write/query load, reduce indexing lag, and provision more RAM.
Add more RAM:
- Upgrade server
- Use cloud instance with more memory
Reduce novelty:
- Index more frequently
- Reduce transaction size
Troubleshooting Checklist
When encountering issues, check:
- Server is running
- Can connect to server
- Health endpoint returns healthy
- Logs show no errors
- Ledger exists
- Correct ledger name/branch
- Valid JSON-LD/SPARQL syntax
- Sufficient resources (disk, memory)
- No network issues
- Authentication working (if required)
Related Documentation
- Debugging Queries - Query-specific debugging
- API Errors - HTTP error reference
- Operations - Operational guides
- Telemetry - Monitoring and logging