microsoft / microsoft/process-migrator
Process Migrator sends explicit field id during createField, causing VS403734 for fields that Azure DevOps UI can create (e.g. @ in name)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 113
- Forks
- 61
- PR merge metrics
- No merged PRs in 30d
Description
Summary
Process Migrator fails to create certain custom fields with error VS403734, even though the same fields can be created successfully via the Azure DevOps UI.
After investigation, the issue appears to be caused by the payload used during field creation. The migrator sends the exported field id (reference name) back to the API, while the Azure DevOps UI uses a minimal payload (id = null, url = null) and lets the server generate the reference name.
This difference in payload causes stricter backend validation and results in a failure for fields that are otherwise valid.
Error
Example:
Create field 'Custom.TestField@'
VS403734: The work item type field reference name Custom.TestField@ isn't valid as it either uses disallowed characters (must have only letters, no spaces, and at least one period (.)), or has a bad length (must be within 1 - 260 characters long).
What we verified
1. UI creation succeeds
Creating a field in Azure DevOps UI with:
Name: "Test Field @"
works successfully.
The resulting field has:
id: Custom.TestField@
2. UI request payload (working)
POST /_apis/work/processDefinitions/{processId}/fields
Request body:
{
"id": null,
"url": null,
"description": "",
"name": "Test Field @",
"type": 1,
"pickList": null
}
Response:
{
"id": "Custom.TestField@",
"name": "Test Field @",
"type": "string",
...
}
3. Migrator behavior (failing)
Exported field example:
{
"id": "Custom.TestField@",
"name": "Test Field@",
"type": 1,
"description": "",
"url": "...",
"isIdentity": false,
"isLocked": false
}
During import, the migrator sends this id back in the createField call.
4. Root cause
Process Migrator reuses a field read-model as a create-model.
It sends:
- id (reference name)
- url
during field creation, instead of letting the backend generate them.
This results in different validation behavior compared to the UI.
5. Local fix (validated)
Changing the create-field payload to match the UI behavior fixes the issue:
- id: null
- url: null
- send only minimal required fields (name, type, description, pickList)
After this change:
- Fields like
Custom.TestField@are created successfully - Migration completes without VS403734
Suggested fix
When calling:
WorkItemTrackingProcessDefinitionsApi.createField(...)
construct a minimal payload similar to the UI:
- id = null
- url = null
- description
- name
- type
- pickList
Then use the returned field id for subsequent operations.
Impact
This blocks migration of inherited processes containing fields whose generated reference names include characters like @, even though Azure DevOps UI supports creating such fields.
Additional notes
A working fix has been implemented and validated in a fork:
https://github.com/sb-devworks/process-migrator/tree/fix-field-create-payload
Happy to provide a pull request if this approach is acceptable.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the import path that calls WorkItemTrackingProcessDefinitionsApi.createField and compare its payload with the minimal Azure DevOps UI payload described here. The work is done when created fields omit the exported id and url, use the returned field id for later operations, and migration succeeds for names such as Custom.TestField@ without VS403734.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, node.js, typescript
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100