The situation is as follows:

In my Salesforce org, I have a contact, let's call it Humpty Dumpty, and I'd like to attach a file to it, let's call it cooking.txt, but there are some rules:

  • If there attachment is already there, overwrite it.
  • If the attachment isn't there, attach it.

For that purpose, I'm using Bulk API and upserts.

request.txt looks like below:

<?xml version="1.0" encoding="UTF-8"?>
<sObjects xmlns="http://www.force.com/2009/06/asyncapi/dataload" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

00P_blah_blah is the ID of the attachment attached to my contact, Humpty Dumpty. My intention is to use it as the external ID field in upsert, so that, if an attachment with that ID already exists, it'll be updated, and if not, it'll be inserted.

In my Java code, I also do this:


where job is an instance of JobInfo.

However, this fails, and the error is:

Errors(fields=null, message=invalid record id, statusCode=INVALID_ID_FIELD)

Anyone knows what could be the reason for this, and how to fix it?

Thanks all!

Update 1

00P_blah_blah and 003_blah_blah are fake IDs of course. In reality, I'm using 18-character IDs.

Update 2

Depending on whether the attachment already exists, and fields I send in, here's how it works:

  • attachment doesn't exist, input has ID and ParentId -> error as above
  • attachment doesn't exist, input has ParentId -> success (attachment is created)
  • attachment exists, input has ID and ParentId -> success (attachment is updated)

Update 3:

I get the same when using SOAP instead of Bulk API:

// Example in Java
SObject obj = new SObject("Attachment");
obj.setField("Id", "id goes here");
obj.setField("ContentType", "text/plain");
obj.setField("Name", "milkshake");
obj.setField("Description", null);
obj.setField("Body", IOUtils.toByteArray(new FileInputStream("/path/to/recipes/milkshake.txt")));
obj.setField("ParentId", "parent id goes here");
partnerConnection.upsert("Id", new SObject[] { obj });

2 Answers 2


You can't set the Id for a create - If you're creating it, SF will provide the ID. If you've given it an ID for an upsert, it'll error out if the record doesn't exist (since you can't set the ID)

If you're providing the ID, where are you getting it from? (if it's from another SF instance, this post has some info:


This SF API doc explains more about the error: Core Data Types Used in API

Here is the relevant text:


The specified ID is correctly formatted, but is not valid, for example, it is an ID of the wrong type, or the object it identifies no longer exists.

  • If I understood you correctly, what you're saying is that you can't use an ID for external ID field in upsert? Apr 11, 2015 at 17:28
  • Well, you can, if you have a field for it, but you can't use the field "Id" - That's a controlled field. Also, since it's an external ID, it's most likely invalid for your SF instance. I've added a link to my post with more details. Apr 13, 2015 at 13:37
  • HungryBeagle, thanks for the link! I read there: Your CSV file must contain a column of ID values for matching against existing records. The column may be either an external ID (a custom field with the “External ID” attribute), or Id (the Salesforce record ID). I'm even more confused.:S Apr 28, 2015 at 8:05

"00P_blah_blah" is not a valid ID field. Record Ids in Salesforce are 15 or 18 digit alphanumeric values.

Also while performing API calls to Salesforce, I believe you would need a 18 digit Record Id as compared to its 15 digit counterpart which may be causing the issue. 18 character Record Id = 15 digit Record Id + 3 checksum chars generated by a specific SFDC algorithm.

Also, one of the items to verify if the attachment specified by the Record Id exists on Salesforce. Try querying Attachment record using SOQL for testing and if that does not return a valid response means the record is not existent !

Use this google chrome extension developed by Appirio to convert 15 character record Ids to 18 characters ones. Hope this helps !

  • Thank you for your response. Please look at Update 1. Also, this record doesn't exist, and in fact, doesn't have to exist. upsert() used the external ID field to see if the record is there or not. If it is, it will update, it not, it will create a new. So it's not required that the record exists. Apr 10, 2015 at 14:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .