askill
sf-bulk-operations

sf-bulk-operationsSafety 85Repository

Salesforce Bulk API 2.0 write operations using the sf CLI. Use when performing bulk data imports, updates, upserts, or deletes via sf data import bulk, sf data update bulk, sf data upsert bulk, sf data delete bulk, or sf data resume. Covers CSV preparation, line endings, job monitoring, error handling, and result retrieval.

0 stars
1.2k downloads
Updated 3/16/2026

Package Files

Loading files...
SKILL.md

Salesforce Bulk Write Operations

Bulk API 2.0 write operations for inserting, updating, upserting, and deleting records via the sf CLI.

Critical: Choose the Right Command

The Bulk API 2.0 does NOT auto-detect the operation from your CSV. Each operation has a separate command:

CommandOperationRequired CSV ColumnUse When
sf data import bulkINSERT(none — creates new records)Loading new records
sf data update bulkUPDATEIdModifying existing records by Salesforce ID
sf data upsert bulkUPSERTExternal ID fieldInsert-or-update by external key
sf data delete bulkDELETEIdRemoving records by Salesforce ID

Common mistake: using import (INSERT) when you need update (UPDATE). If all records fail with INVALID_CROSS_REFERENCE_KEY or duplicate errors, you likely used the wrong command.

CSV Preparation

Line Endings (macOS Gotcha)

The --line-ending flag must match your CSV's actual line endings. On macOS, the default is LF.

Python's csv module writes CRLF (\r\n) by default. To produce LF:

with open("upload.csv", "w", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=["Id", "My_Field__c"], lineterminator="\n")
    writer.writeheader()
    for row in data:
        writer.writerow(row)

Then pass --line-ending LF explicitly:

sf data update bulk --file upload.csv --sobject Account --target-org myorg --line-ending LF --wait 10

If line endings don't match, you'll get: ClientInputError: LineEnding is invalid on user data.

Header Row

  • Use API field names (e.g., Stripe_ATR__c), not field labels (e.g., "Stripe ATR")
  • For update/delete: include an Id column with 18-character Salesforce record IDs
  • For upsert: include the external ID field specified by --external-id

Column Delimiter

Default is comma. Use --column-delimiter for alternatives: BACKQUOTE, CARET, COMMA, PIPE, SEMICOLON, TAB.

Running Bulk Jobs

Always Use --json Output

The progress spinner produces thousands of ANSI escape characters that overflow terminal buffers. Always capture structured output:

sf data update bulk \
  --file upload.csv \
  --sobject Account \
  --target-org production \
  --line-ending LF \
  --wait 10 \
  --json 2>&1 | tail -50

Common Flags

FlagDescription
--filePath to CSV file (required)
--sobjectAPI name of target object (required)
--target-orgOrg alias or username (required)
--line-endingLF or CRLF (default: LF on macOS, CRLF on Windows)
--waitMinutes to wait for completion
--external-idExternal ID field name (upsert only)
--column-delimiterCSV delimiter

Async Jobs

If --wait is omitted or the job exceeds the wait time, the CLI returns a job ID. Resume monitoring with:

sf data import resume --job-id <JOB_ID> --target-org myorg --wait 10 --json
sf data update resume --job-id <JOB_ID> --target-org myorg --wait 10 --json

Inspecting Results

After a job completes (or partially fails):

sf data bulk results --job-id <JOB_ID> --target-org myorg --json

Returns:

{
  "result": {
    "processedRecords": 19852,
    "successfulRecords": 19277,
    "failedRecords": 575,
    "status": "JobComplete",
    "operation": "update",
    "object": "Account",
    "successFilePath": "<JOB_ID>-success-records.csv",
    "failedFilePath": "<JOB_ID>-failed-records.csv"
  }
}

The failed records CSV includes the error reason per row:

"sf__Id","sf__Error",Id,My_Field__c
"","INVALID_CROSS_REFERENCE_KEY:invalid cross reference id:--","001xxx","value"

Clean Up Result Files

Bulk results write CSV files to the current directory. Clean up after inspection:

rm -f <JOB_ID>-success-records.csv <JOB_ID>-failed-records.csv

Sandbox Considerations

When running bulk operations against a sandbox:

  • INVALID_CROSS_REFERENCE_KEY errors are expected for record IDs that exist in production but not in the sandbox (accounts created after the last sandbox refresh, or deleted in sandbox). This is normal — compare success count to total to assess coverage.
  • Sandbox refresh resets data but not metadata. Custom fields created in production should exist in sandbox after refresh.
  • Test with a small subset first (head -100 upload.csv > test.csv) before running the full batch.

Examples

Update a Custom Field on Accounts

# Prepare CSV with LF line endings (Python)
python -c "
import csv
with open('update.csv', 'w', newline='') as f:
    w = csv.DictWriter(f, ['Id','My_Field__c'], lineterminator='\n')
    w.writeheader()
    w.writerow({'Id': '001xxx', 'My_Field__c': '42.50'})
"

# Upload
sf data update bulk \
  --file update.csv \
  --sobject Account \
  --target-org production \
  --line-ending LF \
  --wait 10 \
  --json 2>&1 | tail -50

Upsert by External ID

sf data upsert bulk \
  --file contacts.csv \
  --sobject Contact \
  --external-id External_Id__c \
  --target-org production \
  --line-ending LF \
  --wait 10 \
  --json 2>&1 | tail -50

Delete Records

# CSV needs only the Id column
echo "Id" > delete.csv
echo "001xxx" >> delete.csv

sf data delete bulk \
  --file delete.csv \
  --sobject Account \
  --target-org sandbox \
  --line-ending LF \
  --wait 10 \
  --json 2>&1 | tail -50

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

92/100Analyzed 2/24/2026

High-quality technical skill for Salesforce Bulk API 2.0 operations. Comprehensive coverage of all bulk write operations with excellent actionable examples including Python CSV generation, CLI commands with all flags, result inspection, and sandbox considerations. Well-organized with clear when-to-use guidance, tables for command comparison, and practical warnings about common pitfalls like line endings and wrong operation selection. Located in proper skills folder with relevant tags.

85
95
90
90
95

Metadata

Licenseunknown
Version-
Updated3/16/2026
Publishergrailautomation

Tags

apiobservabilitytesting