Skip to content

Publish API creates 2 schemas on destination API #274

Closed

Description

@TiberiuGarbea

Command that triggered the bug

apiops publish

Expected behavior

When migrating from development to test environment I expect same schema to be created on test environment.

Actual behavior

Checking the extracted artifact they look fine. One schema is available in the artifact and has expected format.
After publish the expected schema is created but also an additional one.
I did another extract on test environment to compare the 2 schemas in the produced artifact schemaInformation.json.
They are very similar only difference I could notice in portal was the location of required array in components ->schemas at the beginning of the items object in the additional schema and at the end in expected schema.
"components": {
"schemas": {
"IngestionRequest": {
"minItems": 1,
"type": "array",
"items": {
"required": [
"type",
"objectClass",
"object",
"parameter",
"eventHost"
],
"type": "object",
"properties": {
"type": {
"type": "string"
},
"protocolVersion": {
"type": "integer"
},
Another difference was the "provisioningState": "Succeeded" present in the original schema.

When visualizing the API Json in portal OpenAPI specification editor the "components": {
"schemas": { } }..are missing and I get below message at the end of the json.

"x-ms-export-notes": ["Definitions/body parameters are not exported since this API references multiple schemas with OpenAPI components as opposed to one. Schemas referenced: 1786466527403,6aa014505ddd1707103c870a"]
}

This issue could be in relatio with issue: #262

apiops CLI version

apiops --version 1.0.1

Environment details

Usage:
npm install -g @azure-tools/apiops-cli --no-fund --no-audit
apiops extract --resource-group ${AZURE_RESOURCE_GROUP_NAME} --service-name ${API_MANAGEMENT_SERVICE_NAME} --output ./apim-artifacts --filter ${CONFIGURATION_YAML_FILE} --format json

Runs in : Gitlab pipeline on self hosted runner with base image: mcr.microsoft.com/dotnet/sdk:6.0
Nodejs version node-v22.14.0-linux-x64
Tried env variable ARM_API_VERSION: "2024-05-01" or no mention leading to -> 2025-09-01-preview
Tried with both formats on export: text and JSON

CI/CD environment

Other

Is this bug blocking you?

Yes

Activity

  1. Alexey-Zheltov commented on Sep 8, 2026

    @Alexey-Zheltov
    Collaborator

    I've been investigating this and can share verification results plus a candidate fix, but I need a few details from your environment to confirm the mechanism.

    What I verified against a live APIM instance: importing an OpenAPI spec through ARM (PUT /apis/{id}?import=true) generates 24-char hex schema IDs on every API version I probed (2021-08-01, 2022-08-01, 2023-05-01-preview, 2024-05-01, 2025-09-01-preview). I could not get ARM spec import to produce a 13-digit ID like 1786466527403 on any version.

    1786466527403 parses as an epoch-milliseconds timestamp (≈ 2026-08-11) — a Date.now()-style ID. Since the schema ID in PUT .../schemas/{schemaId} is chosen by the client, this points at the schema having been created by a different client on your source instance, most likely the Azure portal's OpenAPI specification editor. The duplicate would then be: spec import creates a fresh 24-hex schema on the destination + the CLI re-publishes the 13-digit artifact schema as "explicit" (its auto-generated-ID filter only matches 24-hex), yielding two schemas.

    Candidate fix (treats 13-digit epoch-millis IDs as auto-generated so they are skipped on publish, like their 24-hex counterparts): Alexey-Zheltov/apiops-cli@fix/timestamp-schema-ids

    To confirm this matches your case, could you check:

    1. Which ID does the schema in your extracted artifact have — 1786466527403 or 6aa014505ddd1707103c870a? (i.e. what's under apis/<api>/schemas/<id>/schemaInformation.json)
    2. Which two schema IDs exist on the destination after publish, and which one is the unexpected extra? (GET .../apis/<api>/schemas?api-version=2024-05-01)
    3. Was this API's spec ever edited via the portal's OpenAPI specification editor on the source instance?
    4. What is the contentType of the artifact schema — application/vnd.oai.openapi.components+json?
    5. Do any operations reference that schema (schemaId in request/response representations) in the artifacts?
    6. Is the duplication idempotent — does the schema count stay at 2 on repeated publishes, or grow with each run?

    Answer to (1) is the critical one: if the artifact schema is the 13-digit one, the linked fix should resolve your case; if it's the 24-hex one, the duplicate is produced by a different mechanism and needs more digging.

  2. TiberiuGarbea commented on Sep 8, 2026

    @TiberiuGarbea
    Author

    Hi Aleksey Zheltov (@Alexey-Zheltov) , thanks for looking into this.
    To answer your questions here is a redacted snippet from extracted schemaInformation.json of an api:
    "id": "/subscriptions/1232222222/resourceGroups/my-tes-trg/providers/Microsoft.ApiManagement/service/apim-source-instance/apis/api-name/schemas/1786466527403",
    "type": "Microsoft.ApiManagement/service/apis/schemas",
    "name": "1786466527403",
    "properties": {
    "contentType": "application/vnd.oai.openapi.components+json",
    "document": {
    "components": {
    "schemas": {
    "ApiRequest": {
    "type": "array",
    "minItems": 1,
    "items": {
    "type": "object",

    1. ID the schema in the extracted artifact: 1786466527403
    2. IDs on destination: 1786466527403, 6aa044925ddd1707103c8724 - the unexpected one is 6aa044925ddd1707103c8724
    3. The source is dev, where developers have the ability to modify but there is only one schema based on result from : Api Schema - List By Api
    4. contentType": "application/vnd.oai.openapi.components+json",
    5. Yes
    6. schema count stays at 2 on repeated publishes.
  3. TiberiuGarbea commented on Sep 11, 2026

    @TiberiuGarbea
    Author

    Hi Aleksey Zheltov (@Alexey-Zheltov) , yesterday one of my colleagues did a test:
    fetched the following branch
    https://github.com/Alexey-Zheltov/apiops-cli/tree/fix/timestamp-schema-ids
    build locally and ran the pipeline using this not-yet merged version of apiops-cli.

    What we observed was that indeed there was only one schema on the destination APIs but it was the newly created one and not the original from dev.

    DEV schema:
    "type": "Microsoft.ApiManagement/service/apis/schemas",
    "name": "1758020457424",
    "properties": {
    "contentType": "application/vnd.oai.openapi.components+json"

    TEST schema:
    "type": "Microsoft.ApiManagement/service/apis/schemas",
    "name": "6aa17c915ddd1707103c8815",
    "properties": {
    "contentType": "application/vnd.oai.openapi.components+json"

  4. TiberiuGarbea commented on Sep 11, 2026

    @TiberiuGarbea
    Author

    Hi Aleksey Zheltov (@Alexey-Zheltov), good afternoon. Today we did another test regarding schema transition across environments:
    Expectations:
    Our Expectation is that Schema ID will be kept during migration between environments so that we know that APIs migrated with CICD are consistent across environments and were not altered from Portal.

    Test apiops_cli schema transition across environments
    Apiops_cli version: https://github.com/Alexey-Zheltov/apiops-cli/tree/fix/timestamp-schema-ids
    Envs: APIM Demo1 as source and APIM Demo 2 (newly created) as destination

    Scenario proposed for testing:
    1. Migration from Demo1 to Demo1 - create the second schema -- delete the original schema by hand
    2. Migration Demo1 to Demo2 - Demo2 clean 0 schemas --- you can see what schema we have after publish -- is it the one that came from dev?
    3. Changes in the portal Demo1 - add operation to an API -- query Demo1 schema - Do we have the same schema or more?
    4. Migration Demo1 to Demo2 - is the dev schema kept? How many schemas do we have?

    Results:
    Demo1 source: schema 6aa2987c5ddd17093c34d59e - deleted (1758020457424) could not delete 6aa2987c5ddd17093c34d59e - error, schema linked to operations.

    1. Demo1 to Demo1  -- New schema created: 6aa3f7b15ddd17093c34d605 - previous schema overwritten 
    2. Publish to Demo2 -- New schema create d6aa3f8914634611f80607cc2 - not the same as in source APIM Demo1
    3. Added new operation to Api in Demo1 from portal and saved --no schema changed.
    4. a. Run new pipeline -- extract from Demo1 confirms no schema change after adding an operation
    b. Publish from Demo1 to Demo2 - new schema ID 6aa410c44634611f80607d86 - previous schema overwritten 
    

    Conclusion: Publish creates a new schema ID on every iteration. Event publishing to self will update schema ID. Only one schema was always retrieved per API.

  5. Alexey-Zheltov commented on Sep 11, 2026

    @Alexey-Zheltov
    Collaborator

    Update: I was able to reproduce the full scenario end-to-end, including where the 13-digit ID comes from.

    Where 1786466527403-style IDs originate (verified live):

    The Azure portal generates them client-side (Date.now()), but only on one specific path:

    1. Take an API that has no schema resources yet (e.g. created manually, not via spec import)
    2. Portal → API → Design → open an operation → edit Frontend → Request (or a Response) → Representations → add application/json → New definition with a sample payload
    3. Save

    The portal then does PUT .../schemas/{Date.now()} — the resulting schema name decodes exactly to the millisecond of the Save click (I verified this: my test produced 1789146226316 = the moment I hit Save; yours, 1786466527403, decodes to 2026-08-11 16:42:07 UTC, presumably when one of your developers edited the API on dev).

    For completeness, the other paths do not produce these IDs:

    • ARM spec import (PUT /apis/{id}?import=true) generates 24-hex IDs on every api-version from 2021-08-01 to 2025-09-01-preview
    • The portal's OpenAPI specification editor save triggers a server-side re-import → 24-hex ID
    • Editing an operation when the API already has a schema appends the definition to the existing schema (ID unchanged)

    The duplication mechanism, confirmed: your artifact carries the portal-created 13-digit schema; on publish the spec import creates its own 24-hex schema on the destination, and the CLI additionally re-PUTs the 13-digit one because its auto-generated-ID filter only recognized 24-hex names. Hence exactly two schemas, stable across repeated publishes — matching everything you observed, including the x-ms-export-notes "multiple schemas" message.

    Fix: Alexey-Zheltov/apiops-cli@fix/timestamp-schema-ids — 13-digit epoch-millis schema names are now skipped during publish, but only on the spec-import path for ApiSchema resources (deliberately not widening the general auto-generated-ID predicate, so named values, subscriptions, and operations with numeric names are unaffected). After the fix the destination ends up with the single import-created schema; operation schema bindings are handled by the import itself.

    Two notes for trying it:

    1. One-time cleanup: the stale schema already on your test instance won't be deleted by the fix — remove it once manually:
      az rest --method delete --url ".../apis/<api>/schemas/1786466527403?api-version=2024-05-01"
    2. After the fix, the destination schema will have a different (24-hex) ID than the source's 13-digit one. Content is identical; ID parity is not preserved for machine-generated schemas (same as for 24-hex ones today).

    On the #262 relation: unrelated to schema IDs. I reproduced the 24h→12h time mangling with plain az rest and no apiops involved: importing a spec whose schema example contains "2026-07-11T14:01:26.0000000+00:00" stores it as "2026-07-11T02:01:26Z". That's APIM's own OpenAPI serializer (a .NET hh-vs-HH format defect) re-serializing the spec on import — consistent with your observation that the archived .NET apiops v7.0.4 shows the same corruption. #262 is an APIM service defect, not a CLI bug; worth raising with the APIM product group.

  6. added a commit that references this issue on Sep 21, 2026
    5cb17b1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    close:fixedFixed by a previous PR or releasetype:bugSomething broken

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions