Docs

TurboBulk Troubleshooting Guide

This guide covers common issues, error messages, and solutions when using TurboBulk.

Common Errors

Foreign Key Errors

ErrorCauseResolution
FK value=0Wrong FK column nameUse _id suffix (e.g., site_id not site)
foreign key violationReferenced object doesn't existLoad parent objects first
site_id=999 references a dcim_site that does not existInvalid FK valueVerify the referenced object exists

Example fix for FK column naming:

# WRONG - causes FK value=0
table = pa.table({
    'name': ['device-1'],
    'site': [123],  # Wrong! Missing _id suffix
})

# CORRECT
table = pa.table({
    'name': ['device-1'],
    'site_id': [123],  # Correct: uses _id suffix
})

Unique Constraint Errors

ErrorCauseResolution
unique constraint violationDuplicate key in dataDeduplicate source data
duplicate key value violates unique constraintRecord already existsUse mode='upsert' instead of insert

Solutions:

  1. Deduplicate your source data before loading
  2. Use upsert mode for data that may already exist:
    curl -X POST ... -F "mode=upsert" -F "conflict_fields=name" ...

Schema Errors

ErrorCauseResolution
schema mismatchParquet columns don't match modelRegenerate schema from /models/ endpoint
NOT NULL violationRequired field missingInclude all required fields
string_too_longValue exceeds max lengthTruncate strings to fit field limits

Getting the correct schema:

curl -H "Authorization: Bearer $TOKEN" \
  "$NETBOX_URL/api/plugins/turbobulk/models/dcim.device/"

Pre-Validation Errors

TurboBulk runs pre-validation for IP addresses and prefixes (models with inet-based rules):

ErrorCauseResolution
Rule ipaddress_network_broadcast found N violationsIP address is network/broadcast addressUse host addresses (e.g., 10.0.0.1/24 not 10.0.0.0/24)
Rule ipaddress_vrf_uniqueness found N violationsDuplicate IP in VRF with enforce_unique=TrueUse unique IP or different VRF
Rule prefix_network_portion found N violationsPrefix has non-zero host bitsUse network address (e.g., 10.0.0.0/24 not 10.0.0.5/24)
Rule prefix_vrf_uniqueness found N violationsDuplicate prefix in VRF with enforce_unique=TrueUse unique prefix or different VRF

Validation modes:

  • validation_mode=auto (default): Pre-validation for IP addresses and prefixes
  • validation_mode=full: Django full_clean() on each row (slower but catches all issues)
  • validation_mode=none: Skip pre-validation (fastest, use for trusted data only)

Example:

# Force full Django validation for complex models
curl -X POST -H "Authorization: Bearer $TOKEN" \
  -F "model=dcim.cable" \
  -F "mode=insert" \
  -F "validation_mode=full" \
  -F "file=@cables.parquet" \
  "$NETBOX_URL/api/plugins/turbobulk/load/"

# Skip validation for trusted migration data
curl -X POST -H "Authorization: Bearer $TOKEN" \
  -F "model=dcim.site" \
  -F "mode=insert" \
  -F "validation_mode=none" \
  -F "file=@sites.parquet" \
  "$NETBOX_URL/api/plugins/turbobulk/load/"

Permission Errors

ErrorCauseResolution
permission deniedUser lacks model permissionsRequest permissions from your administrator
User lacks permission: dcim.add_deviceMissing add permissionRequest add_device permission
TurboBulk write operations are disabledPlugin configured with enable_writes: FalseAsk your administrator to set enable_writes to True in PLUGINS_CONFIG['netbox_turbobulk']

Required permissions by operation:

  • Insert: add permission on target model
  • Upsert: add + change permissions
  • Delete: delete permission
  • Export: view permission

File Upload Errors

ErrorCauseResolution
File size exceededUpload too largeSplit your data into smaller files
Invalid Parquet fileCorrupted or wrong formatVerify file with parquet-tools or PyArrow

Checking your Parquet file:

import pyarrow.parquet as pq

table = pq.read_table('devices.parquet')
print("Schema:", table.schema)
print("Rows:", table.num_rows)

Branch Errors

ErrorCauseResolution
Branch not foundBranch doesn't existCreate the branch first via NetBox UI or API
Branch is not in READY stateBranch is provisioningWait for READY status
Branching not availableFeature not enabledContact support

Job Errors

ErrorCauseResolution
Job timeoutOperation took too longSplit data into smaller files
Job not foundInvalid job IDVerify job ID from submit response
Job erroredOperation failedCheck job data.error for details

Debugging Workflow

1. Check Job Status

# Get detailed job status
curl -H "Authorization: Bearer $TOKEN" \
  "$NETBOX_URL/api/plugins/turbobulk/jobs/{job_id}/"

The response includes:

  • status: pending, running, completed, errored
  • data.error: Detailed error information
  • data.rows_processed: Progress indicator

2. Use Dry-Run Mode

Validate your data before committing:

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -F "model=dcim.device" \
  -F "mode=insert" \
  -F "dry_run=true" \
  -F "file=@devices.parquet" \
  "$NETBOX_URL/api/plugins/turbobulk/load/"

Dry-run performs all validation including:

  • Schema validation
  • FK constraint checking
  • Unique constraint checking
  • NOT NULL validation

3. Validate Parquet File Locally

Check your Parquet file structure before uploading:

import pyarrow.parquet as pq

# Read and inspect
table = pq.read_table('devices.parquet')
print("Schema:", table.schema)
print("Rows:", table.num_rows)
print("Columns:", table.column_names)

# Check for null values in required fields
for col in table.column_names:
    nulls = table.column(col).null_count
    if nulls > 0:
        print(f"WARNING: {col} has {nulls} null values")

4. Verify API Connectivity

# Test API access
curl -H "Authorization: Bearer $TOKEN" \
  "$NETBOX_URL/api/plugins/turbobulk/models/" | head -5

Performance Issues

Slow Imports

SymptomCauseSolution
Import slower than expectedChangelogs enabledSet create_changelogs=false for bulk imports
Very large filesProcessing overheadSplit into files of 100K-500K rows
TimeoutsOperation takes too longSplit data into smaller batches

Optimizing for speed:

# Disable changelogs for large initial imports
curl -X POST ... -F "create_changelogs=false" -F "file=@devices.parquet" ...

Export Cache Issues

SymptomCauseSolution
Always getting fresh exportsData changed since last exportThis is expected behavior
Want to force fresh exportUsing cached dataUse force_refresh=true
Want to check if cache validClient-side optimizationUse check_cache_only=true

Understanding Error Messages

TurboBulk provides detailed, user-friendly error messages:

{
  "data": {
    "error": {
      "error_type": "foreign_key",
      "message": "Foreign key violation: site_id=999 references a dcim_site that does not exist",
      "column": "site_id",
      "value": "999",
      "suggestion": "Ensure that the referenced site exists before inserting"
    }
  }
}

Error types:

TypeMeaning
foreign_keyReferenced object doesn't exist
uniqueDuplicate key in your data
not_nullRequired field is missing
checkValue fails a constraint (e.g., invalid status)
data_typeWrong data type for field
string_too_longString exceeds field's max_length

Transaction Safety

TurboBulk operations are atomic - if any part fails, the entire operation rolls back:

  • No partial data is committed
  • Your NetBox data remains in a consistent state
  • You can safely retry after fixing the issue

This means you don't need to worry about cleanup after failures.

Getting Help

  1. Check job status - The error details often explain the issue
  2. Use dry-run - Validate before committing
  3. Check permissions - Verify user has required permissions
  4. Verify FK values - Ensure referenced objects exist

Contact Support

For issues you can't resolve:

  • NetBox Cloud/Enterprise customers: Contact NetBox Labs support
  • Include in your request:
    • Job ID
    • Error message
    • Parquet file schema (not the data)
    • Steps to reproduce

On this page