$ref inside $defs 400 bad request error

I’m trying to extract data using this JSON schema (I’m using a $ref inside the $defs - or more concrete I want an opportunity to reference a contact):

{
    "type": "object",
    "properties": {
      "contacts": {
        "type": "array",
        "items": {
          "$ref": "#/$defs/contact"
        }
      },
      "accounts": {
        "type": "array",
        "items": {
          "$ref": "#/$defs/account"
        }
      },
      "opportunities": {
        "type": "array",
        "items": {
          "$ref": "#/$defs/opportunity"
        }
      }
    },
    "required": ["contacts", "accounts", "opportunities"],
    "additionalProperties": false,
    "$defs": {
      "contact": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "email": {
            "type": ["string", "null"]
          },
          "job_title": {
           "type": ["string", "null"]
          },
          "phone": {
            "type": ["string", "null"]
          },
          "name_prefix": {
            "type": ["string", "null"]
          },
          "gender": {
            "type": ["string", "null"]
          },
          "language": {
            "type": ["string", "null"]
          },
          "account_name": {
            "type": ["string", "null"]
          }
        },
        "required": ["name", "email", "job_title", "phone", "name_prefix", "gender", "language", "account_name"],
        "additionalProperties": false
      },
      "account": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          }
        },
        "required": ["name"],
        "additionalProperties": false
      },
      "opportunity": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "investment_sum": {
            "type": ["number", "null"]
          },
          "valuation": {
            "type": ["number", "null"]
          },
          "pre_money": {
            "type": ["boolean", "null"]
          },
          "investment_type": {
            "type": ["string", "null"],
            "enum": ["share_deal", "convertible"]
          },
          "investment_round": {
            "type": ["string", "null"],
            "enum": ["Preseed", "Seed", "Series A", "Series B", "Series C", "Series D", "Series E", "Series F"]
          },
          "account_name": {
            "type": ["string", "null"]
          },
          "arr": {
            "type": ["number", "null"]
          },
          "mrr": {
            "type": ["number", "null"]
          },
          "number_of_customers": {
            "type": ["number", "null"]
          },
          "number_of_active_users": {
            "type": ["number", "null"]
          },
          "month_on_month_growth": {
            "type": ["number", "null"]
          },
          "year_on_year_growth": {
            "type": ["number", "null"]
          },
          "contacts": {
            "type": "array",
            "items": {
              "$ref": "#/$defs/contact"
            }
          }
        },
        "required": ["name", "notes", "investment_sum", "valuation", "pre_money", "investment_type", "investment_round", "account_name", "arr", "mrr", "number_of_customers", "number_of_active_users", "month_on_month_growth", "year_on_year_growth", "contacts"],
        "additionalProperties": false
      }
    }
  }

When I post this to the API I’ll get a 400 Bad Request error: Invalid schema for response_format ‘data_extraction’. Please ensure it is a valid JSON Schema.

When I use an external validator the schema is marked as valid.
When I inline all the contact properties inside the related_contacts array the extraction works as expected.

Is it possible that $ref inside $defs is not supported?

3 Likes

Hi sebastian.deutsch, did you come up with a solution to this problem, as I’m having a similar situation that $ref inside the $defs doesn’t work, but I can’t expand my schema description without using $ref :frowning:

1 Like

I think I found the problem. If you remove “null” everywhere in $defs (instead of “type”: [“string”, “null”] write “type”: “string”), then everything works. But there is still an issue with specifying the optionality of the field :frowning:

1 Like

Having some issue, looks like a bug, something like this works:

    pid: {
      anyOf: [{ type: 'string' }, { type: 'null' }],
      description: 'The ID of the parent space'
    }

anyOf is not currently supported.

I type this into the playground site’s “generate” creator of response schemas:

This JSON schema object has an anyOf with two subschemas with two different names and two different keys. The first subschema has name answer and the key response to user, and the second subschema has name refusal and the key refusal reason. Produce this full response schema.

And receive my product (just a bit off from what is desired).

{
  "name": "response_schema",
  "strict": true,
  "schema": {
    "type": "object",
    "properties": {
      "response": {
        "anyOf": [
          {
            "$ref": "#/$defs/answer_schema"
          },
          {
            "$ref": "#/$defs/refusal_schema"
          }
        ]
      }
    },
    "required": [
      "response"
    ],
    "additionalProperties": false,
    "$defs": {
      "answer_schema": {
        "type": "object",
        "properties": {
          "answer": {
            "type": "string",
            "description": "The answer provided in response to the user."
          },
          "response": {
            "type": "string",
            "description": "Confirmation of the answer given to the user."
          }
        },
        "required": [
          "answer",
          "response"
        ],
        "additionalProperties": false
      },
      "refusal_schema": {
        "type": "object",
        "properties": {
          "refusal": {
            "type": "string",
            "description": "Indicates that the answer cannot be provided."
          },
          "reason": {
            "type": "string",
            "description": "The reason for not providing an answer."
          }
        },
        "required": [
          "refusal",
          "reason"
        ],
        "additionalProperties": false
      }
    }
  }
}

refs and defs for the non-flat schema besides the anyOf.

then demonstrated

and demonstrated preventing misuse of the children’s story creator.

The top level must be an object.

I ran into this too and also found that replacing "type": ["string", "null"] with "anyOf": [{"type": "string"}, {"type": "null"}] makes the schema work.

Below are two equivalent schemas, the first using "type" and the second using "anyOf". The diff between them is just

diff --git a/Users/matt/Desktop/bad-schema.json b/Users/matt/Desktop/good-schema.json
index 723c24d8e7b..3dfb0696fa5 100644
--- a/Users/matt/Desktop/bad-schema.json
+++ b/Users/matt/Desktop/good-schema.json
@@ -19,7 +19,10 @@
       "additionalProperties": false,
       "properties": {
         "sourceUrl": {
-          "type": ["string", "null"]
+          "anyOf": [
+            {"type": "string"},
+            {"type": "null"}
+          ]
         },
         "label": { "type": "string" },
         "fact": { "type": "string" }

1. Bad schema using "type"

{
  "$defs": {
    "Project": {
      "type": "object",
      "required": ["name", "description", "facts"],
      "additionalProperties": false,
      "properties": {
        "name": { "type": "string" },
        "description": { "type": "string" },
        "facts": {
          "type": "array",
          "items": { "$ref": "#/$defs/Fact" }
        }
      }
    },
    "Fact": {
      "type": "object",
      "required": ["label", "fact", "sourceUrl"],
      "additionalProperties": false,
      "properties": {
        "sourceUrl": {
          "type": ["string", "null"]
        },
        "label": { "type": "string" },
        "fact": { "type": "string" }
      }
    }
  },
  "type": "object",
  "required": ["project"],
  "additionalProperties": false,
  "properties": {
    "project": { "$ref": "#/$defs/Project" }
  }
}

2. Good schema using "anyOf"

{
  "$defs": {
    "Project": {
      "type": "object",
      "required": ["name", "description", "facts"],
      "additionalProperties": false,
      "properties": {
        "name": { "type": "string" },
        "description": { "type": "string" },
        "facts": {
          "type": "array",
          "items": { "$ref": "#/$defs/Fact" }
        }
      }
    },
    "Fact": {
      "type": "object",
      "required": ["label", "fact", "sourceUrl"],
      "additionalProperties": false,
      "properties": {
        "sourceUrl": {
          "anyOf": [
            {"type": "string"},
            {"type": "null"}
          ]
        },
        "label": { "type": "string" },
        "fact": { "type": "string" }
      }
    }
  },
  "type": "object",
  "required": ["project"],
  "additionalProperties": false,
  "properties": {
    "project": { "$ref": "#/$defs/Project" }
  }
}
1 Like