Skip to main content
Importing from object storage is the most efficient and cost-effective way to load large numbers of records into an index. To run through this guide in your browser, see the Bulk import colab notebook.
This feature is available on Standard and Enterprise plans.

Before you import

Before you can import records, ensure you have a serverless index, a storage integration, and data uploaded to an Amazon S3 bucket, Google Cloud Storage bucket, or Azure Blob Storage container. Your uploaded data must be in the file format required for your index type: Parquet for vector indexes, or JSON Lines (JSONL) for indexes with a document schema. If your source data isn’t already in that format, prepare it in that format before uploading.

1. Create an index

Create a serverless index for your data. Be sure to create your index on a cloud that supports importing from the object storage you want to use:

2. Add a storage integration

To import records from a public data source, a storage integration isn’t required. However, to import records from a secure data source, you must create an integration to allow Pinecone access to data in your object storage. See the following guides:

3. Prepare your data

1

Create a directory for each namespace

In your Amazon S3 bucket, Google Cloud Storage bucket, or Azure Blob Storage container, create an import directory containing a subdirectory for each namespace you want to import into. The namespaces must not yet exist in your index.For example, to import data into the namespaces example_namespace1 and example_namespace2, your directory structure would look like this:
To import into the default namespace, use a subdirectory called __default__. The default namespace must be empty.
2

Create a data file for each namespace

For each namespace, create one or more files defining the data to import. The file format and required fields depend on the index type:
To import into a namespace in an index with a document schema, use JSONL (.jsonl, or gzip-compressed .jsonl.gz) files instead of Parquet. Each line is one document, identical in shape to a document you would pass to documents.upsert:
Unlike Parquet imports, fields not declared in the schema aren’t ignored: they are stored and auto-indexed as filterable metadata.
For example, for a schema with a full-text body field and a dense_vector embedding field:
For the full file format, per-field encoding, and directory layout, see Bulk import.
3

Upload the files

Upload the files into the relevant subdirectory.For example, if you have subdirectories for the namespaces example_namespace1 and example_namespace2 and upload 4 files into each, your directory structure would look as follows after the upload. Files use the .parquet extension for vector indexes, or .jsonl / .jsonl.gz for document-schema indexes:

4. Import records into an index

Review import limits before starting an import.
The examples below use Parquet files, for indexes without a schema definition. Indexes with document schemas import JSONL files instead. Semantic-text (auto-embedded) fields aren’t yet supported in document schemas.
Use the start_import operation to start an asynchronous import of vectors from object storage into an index.
  • For uri, specify the URI of the bucket and import directory containing the namespaces and Parquet files you want to import. For example:
    • Amazon S3: s3://BUCKET_NAME/IMPORT_DIR
    • Google Cloud Storage: gs://BUCKET_NAME/IMPORT_DIR
    • Azure Blob Storage: https://STORAGE_ACCOUNT.blob.core.windows.net/CONTAINER_NAME/IMPORT_DIR
  • For integration_id, specify the Integration ID of the Amazon S3, Google Cloud Storage, or Azure Blob Storage integration you created. The ID is found on the Storage integrations page of the Pinecone console.
    An Integration ID isn’t needed to import from a public bucket.
  • For error_mode, use continue or abort.
    • With abort, the operation stops if any records fail to import.
    • With continue, the operation continues on error, but there isn’t any notification about which records, if any, failed to import. To see how many records were successfully imported, use the describe an import operation.
The response contains an id that you can use to check the status of the import:
Response
Once all the data is loaded, the index builder indexes the records, which usually takes at least 10 minutes. During this indexing process, the expected job status is InProgress, but 100.0 percent complete. Once all the imported records are indexed and fully available for querying, the import operation is set to Completed. If you cancel the import before it finishes, the status changes to Cancelled.
You can start a new import using the Pinecone console. Find the index you want to import into, and click the ellipsis (…) menu > Import data.

5. Track import progress

The amount of time required for an import depends on various factors, including:
  • The number of records to import
  • The number of namespaces to import, and the number of records in each
  • The total size (in bytes) of the import
To track an import’s progress, check its status bar in the Pinecone console or use the describe_import operation with the import ID:
The response contains the import details, including the import status, percent_complete, and records_imported:
Response
If the import fails, the response contains an error field with the reason for the failure. See the Troubleshooting section for more information.
Response

Manage imports

List imports

Use the list_imports operation to list all of the recent and ongoing imports. By default, the operation returns up to 100 imports per page. If the limit parameter is passed, the operation returns up to that number of imports per page instead. For example, if limit=3, up to 3 imports are returned per page. Whenever there are additional imports to return, the response includes a pagination_token for fetching the next page of imports.
When using the Python SDK, list_import paginates automatically.
Python
Response
You can view the list of imports for an index in the Pinecone console. Select the index and navigate to the Imports tab.

Cancel an import

The cancel_import operation cancels an import if it isn’t yet finished. It has no effect if the import is already complete.
Response
You can cancel your import using the Pinecone console. To cancel an ongoing import, select the index you are importing into and navigate to the Imports tab. Then, click the ellipsis (…) menu > Cancel.

Import limits

If your import exceeds these limits, you’ll get an error specifying the limit exceeded. See Troubleshooting for details.
The total input data size limit does not apply to indexes with dedicated read nodes. Bulk import supports indexes without a schema definition (Parquet files) and indexes with document schemas (JSONL files). Semantic-text (auto-embedded) fields are not yet supported in document schemas. Also:
  • You can’t import data from an AWS S3 bucket into a Pinecone index hosted on GCP or Azure.
  • You can’t import data from S3 Express One Zone storage.
  • You can’t import data into an existing namespace.
  • When importing data into the __default__ namespace of an index, the default namespace must be empty.
  • Each import takes at least 10 minutes to complete.
  • When importing into an index with integrated embedding, records must contain vectors, not text. To add records with text, you must use upsert.

Troubleshooting

When an import fails, you’ll see an error message with the reason for the failure in the Pinecone console or in the response to the describe an import operation.
You can’t import data into an existing namespace. If your import directory structure contains a folder with the name of an existing namespace in your index, the import will fail with the following error:
To fix this, rename the folder to use a namespace name that doesn’t yet exist.
In object storage, your directory structure must be as follows:
If a Parquet file isn’t nested under a namespace subdirectory, the import will fail with the following error:
To fix this, move the Parquet file to a namespace subdirectory.
Each namespace subdirectory must contain Parquet files with data to import. If a namespace subdirectory doesn’t include Parquet files, the import will fail with the following error:
To fix this, add Parquet files to the namespace subdirectory.
For document-schema (JSONL) imports, an empty namespace subdirectory behaves differently than for Parquet. A namespace subdirectory that contains no .jsonl or .jsonl.gz files is silently skipped: the import doesn’t create that namespace and doesn’t raise an error for it. If a namespace is missing after an import that otherwise succeeded, confirm its subdirectory actually contains importable files.If no importable files are found anywhere under the dataset prefix, the import fails with the same No Parquet files found error shown above, which says “Parquet files” even for JSONL imports.
In your start import request, the import uri must specify only the bucket and import directory containing the namespaces and Parquet files you want to import. If the uri also contains a namespaces directory or a Parquet filename, the import will fail with the following error:
To fix this, remove the namespaces directory or Parquet filename from the uri.
When a Parquet file isn’t formatted correctly, the import will fail with a message like one of the following:
File schema errors
File corruption errors
Type errors
These errors are returned for both continue and abort error modes.To fix these errors, check the specific error message and follow the instructions in the Prepare your data section.
For document-schema indexes, import files are JSONL: each line is one JSON document, validated against the index’s schema. A line fails if it isn’t valid JSON, or if the document doesn’t conform to the schema. Each per-document error identifies the file name, row number, and document _id:
Common reasons include:
Malformed JSON
Empty _id
Dense-vector dimension mismatch
Reserved field name
Wrong field type
A document that omits _id entirely fails JSON parsing and appears as a malformed-JSON error (missing field _id).With errorMode.onError set to continue (the default), invalid documents are skipped and the rest import; with abort, the import stops on the first invalid document. If every document in a namespace is skipped, the import fails with No vectors added, all rows were skipped for namespace: {namespace}.To fix these errors, validate your documents against the file-format rules before importing.
When the error_mode is abort and a file contains invalid records, the import will stop processing on the first invalid record and return an error message identifying the file name and row:
This will be followed by an error message identifying the specific issue. For example:
Missing values
Invalid metadata
Invalid vectors
When the error_mode is continue, the import will skip individual invalid records. However, if all records are invalid and skipped (for example, the vector type in the file doesn’t match the vector type of the index), the import will fail with a general message:
To fix these errors, check the specific error message and follow the instructions in the Prepare your data section.
When your import contains duplicate vectors (records with identical vector values), the duplicates are marked as skipped and not imported. Only one occurrence of each unique vector is added to the index.This applies to both continue and abort error modes:
  • With abort: The import fails when it encounters a duplicate vector within the import.
  • With continue: The import proceeds, skipping duplicate records silently.
Example scenario: If your Parquet file contains:
Only records 1 and 3 will be imported.To prevent this from happening, deduplicate your source data before creating Parquet files by removing records with identical vector values.
On-demand indexes have a maximum total input data size of 1 TB per import. If your import exceeds this limit, it will fail with the following error:
To fix this, either reduce the total size of your import to under 1 TB, use an index with dedicated read nodes (which have no total data size limit for imports), or contact support.For .jsonl.gz files, size is measured as an estimated uncompressed size of 10× the compressed file, so gzip-compressed files count roughly 10× their on-disk size against this limit.

See also