Getting Past the “This is not a valid schemaAttribute” Error When Trying to Create a Field

Creating a field – regardless of whether you’re using the Configuration APIs or Console’s Registration Builder – is a pretty simple task. How simple? Well, here’s a Curl command that creates a field (userFullName) that maps to the displayName attribute:

curl -L -X POST \
  'https://v1.api.us.janrain.com/config/79y4mqf2rt3bxs378kw5479xdu/flows/testFlow/fields' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Basic eTR4Zmc2ZjQ0bXNhYzN2ZXBqanZ4Z2d6dnQzZTNzazk6OTVjY3hrN2N6YnZ1eng2ZHB0ZTVrOXA2ZGo1Ynpla3U=' \
  --data-raw '{
    "type": "text",
    "name": "userFullName",
    "schemaAttribute": "displayName"
}'

Believe it or not, that's all there is to it. All you have to do is: 

  1. Define the datatype (text).
  2. Give your field a name (userFullName).
  3. Map the field to a schema attribute (displayName).

It’s a simple and practically foolproof system … at least until you encounter an error similar to this one:

{    "errors": {
        "schemaAttribute": [
            "newsletterSubscriber is not a valid schemaAttribute. It must be one of consents.personalizedAds.context, consents.personalizedAds.type, fullName, consents.personalizedAds.updated, primaryAddress.zipPlus4, primaryAddress.stateAbbreviation, [photos].id, id, [profiles].identifier, lastLogin, primaryAddress.company, [photos].type, lastUpdated, [legalAcceptances].legalAcceptanceId, primaryAddress.country, [profiles].domain, givenName, primaryAddress.city, consents.marketing.context, mobileNumberVerified, externalId, gender, [roles].id, emailVerified, [roles].display, created, [photos].value, accountDataRequestTime, middleName, [clients].id, [profiles].providerSpecifier, [legalAcceptances].clientId, accountDeleteRequestTime, [profiles].id, display, [legalAcceptances].id, [roles].value, consents.marketing.updated, consents.marketing.granted, email, primaryAddress.address2, [profiles].provider, consents.personalizedAds.granted, consents.marketing.type, displayName, consents.marketing.clientId, consents.personalizedAds.clientId, password, primaryAddress.address1, primaryAddress.phone, [clients].name, birthday, username, uuid, [legalAcceptances].dateAccepted, familyName, mobileNumber, [clients].lastLogin, primaryAddress.zip, [clients].firstLogin, [clients].clientId, deactivateAccount."
        ]
    }
} 

Before you ask, yes, newsletterSubscriber is a valid attribute; we can verify that by going to the Manage Schemas page in Console and looking at the GREG_DEMO schema:

And there’s nothing wrong with our Curl command, either; in fact, we get the exact same error (in the form of a gigantic error message that flashes on at the bottom of the screen and then disappears) if we try to create this field in Registration Builder:

In other words, the attribute is in the schema, we’re using the right approach (in this case, the right two approaches), and yet we still can’t create a field using the newsletterSubscriber attribute. And our problems aren’t limited to newsletterSubscriber; as it turns out, we can’t create any field that map to a custom attribute.

If you’re thinking, “I’m not sure how, but this story must have a happy ending,” well, you’re in luck: this story does have a happy ending. As it turns out, any time you try to add a new field to a flow, the flow checks to see if the schema attribute you're mapping to actually exists. By default, the flow checks the the user schem to see if it can find the attribute. If it can, the field is created. If it can’t, well, then your API call (or your Registration Builder action) fails with an error similar to newletterSubscriber is not a valid schemaAttribute.

That explains why we’re unable to create the field: by default, the flow looks for attributes in the user schema. In this case, that's a problem: our newsletterSubscriber attribute is in a custom schema named GREG_DEMO. That can, and does, mean only one thing: if we want to create a field that maps to the newsletterSubscriberattribute, we need to tell the flow to check the GREG_DEMO schema as well as the user schema.

And how do we do that? By making an API call similar to this one:

curl -L -X PUT \
  'https://v1.api.us.janrain.com/config/79y4mqf2rt3bxs378kw5479xdu/flows/testFlow' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Basic eTR4Zmc2ZjQ0bXNhYzN2ZXBqanZ4Z2d6dnQzZTNzazk6OTVjY3hrN2N6YnZ1eng2ZHB0ZTVrOXA2ZGo1Ynpla3U=' \
  --data-raw '{
    "schemas": [
      "user",
      "GREG_DEMO"
    ],
    "userData": [
      "email",
      "displayName",
      "familyName",
      "primaryAddress.country"
    ]
}'

What we’ve done in the preceding API call is add the GREG_DEMO schema to the flow’s schemas property; by doing that the flow will check both user and GREG_DEMO for attributes referenced when creating new fields. In turn, that means we’ll be able to create a field that references the newsletterSubscriber attribute. In fact, here’s the response we get to the same API call after GREG_DEMO has been added to the schemas property:

{
    "type": "checkbox",
    "submitValue": "true",
    "preChecked": false,
    "schemaAttribute": "newsletterSubscriber",
    "name": "newsletterSubscriber",
    "_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/testFlow/fields/newsletterSubscriber2"
}

That means that everything worked. And that gives us our happy ending.

A few quick notes about updating the schemas property before we go:

  • Our API call for updating schemas uses the /flows/{flow} endpoint and the PUT method. Because we’re using the PUT method, we need to specify all the flow properties in the API call, both the current properties and the properties you’re adding. To make sure you don’t overlook any of those properties, it’s a good idea to start by using the GET method to return all the current properties of the flow. Paste those properties and their values into the body parameter of your API call and then add in any new properties/property values (which, in our cases, means adding GREG_DEMO to the schemas property).

    Oh, and this can only be done using an API call. You can't update the schemas property in Console.

  • ·In our sample API call, we listed both user and GREG_DEMO  in the schemas property. Including the user schema is actually optional: flows always check the user schema. But explicitly listing user makes it easier for someone else to know which schemas are checked any time a new field is created.

  • As usual, spelling counts, and so does letter-casing. If you try to add a schema named greg_dem. oyour API call will fail with an error similar to this one:
    {
        "errors": {
            "schemas": [
                "greg_demo is not a valid schema."
            ]
        }
    }

There’s no doubt that, the first time you encounter the newsletterSubscriber is not a valid schemaAttribute error the experience can be a little … frustrating …. But, as you can see, there’s a simple explanation behind this seemingly-complicated error, and an even-easier way to fix the problem.