Troubleshooting
Use this page to diagnose a failed request or a response that doesn't contain what you expected. Each issue lists the likely causes and how to fix them. For the meaning of a specific error code, see Errors.
Most problems can be traced to one of the following. Check them first.
- The
Authorization header contains Bearer {token} with a token less than 60 minutes old. - The
Content-Type header is application/json. - The request uses the base URL for your region and the path
/portfolioanalysis/v1/xray. - The body includes both
Portfolios and RequestSettings, and RequestSettings includes OutputCurrency. - Every holding has one identifier and one position size, and all holdings in a portfolio use the same position size type.
A 400 response contains a Message and a SpecificErrorStatus array. Each entry describes one problem, so read every entry, not just the first.
{
"Message": "The request is invalid.",
"SpecificErrorStatus": [
{
"ErrorCode": "40015",
"ErrorMessage": "Portfolio does not have any valid holdings. Invalid portfolio name: TestPortfolio1. Invalid Holdings: TradingSymbol:DODGX1."
}
]
}
The ErrorMessage often names the portfolio and the holding that caused the problem. Use the ErrorCode to look up the issue in the sections below or on the Errors page.
The token is missing, invalid or expired.
- Check that the `Authorization` header is present and uses the format `Bearer {token}`.
- Tokens expire after 60 minutes. Request a new token from the Authentication API using `POST /token/oauth`, then retry the request.
- In long-running jobs, refresh the token before it expires, and retry any request that returns `401` after refreshing.
See [Authentication](/api-authentication).
The request was authenticated but access was refused. Confirm that your account is licensed for the Portfolio X-Ray API. Your Morningstar account manager can confirm what your agreement includes.
An error occurred on the server. Check that the request body is valid JSON, then retry the request. If the error persists, contact Morningstar support with the request body and the time of the request.
The request doesn't contain any portfolios. Add at least one portfolio object to the `Portfolios` array. Check that the property is spelled `Portfolios` and is an array, even when it contains a single portfolio.
None of the holdings in the named portfolio could be matched to a security you are entitled to. The error message lists the portfolio name and the holdings that failed, for example `TradingSymbol:DODGX1`.
- Check each identifier for typos and extra characters.
- Confirm the identifier type matches the property. For example, an ISIN must be passed in `ISIN`, not `TradingSymbol`.
- Try a different identifier for the same security. A Morningstar `SecurityId` or `PerformanceId` is the most precise. Use the Universe API to look up Performance IDs in your entitled universe.
- Confirm that you are entitled to the securities. Unentitled holdings are treated in the same way as invalid ones.
When `DisableRescale` is `true` and any holding is invalid or unentitled, the request fails. The `Metadata` object lists each affected holding and its status.
```json
"Metadata": {
"InvalidPortfolios": [
{
"Name": "Test Portfolio",
"InvalidHoldings": [
{ "SecurityId": "FX000015JA3", "Status": "Invalid" },
{ "SecurityId": "F00000YZ48", "Status": "Unentitled" }
]
}
]
}
```
- For holdings with the status `Invalid`, correct or replace the identifier.
- For holdings with the status `Unentitled`, remove the holding or contact your Morningstar account manager about access.
- If you prefer the analysis to continue without these holdings, set `DisableRescale` to `false`.
The `View` ID isn't recognized. Use one of `All`, `Default`, `Intersection`, `Operation`, `Portfolio`, `StockIntersection`, `XrayOverview` or `Snapshot`, spelled exactly as shown. The view must be passed as an object:
```json
"View": { "Id": "Snapshot" }
```
`AnalysisDateTimePeriod` is set to `CustomDate`, but `PortfolioPerformanceEndDate` isn't set. Add the end date in `YYYY-MM-DD` format, or change `AnalysisDateTimePeriod` to `MonthEnd`, `QuarterEnd` or `YearEnd`.
The same rule applies to the start date: when `PortfolioPerformanceStartDate` is `CustomDate`, you must also set `PortfolioPerformanceCustomStartDate`.
The fee settings on the portfolio and on its holdings conflict. For example, `40027` is returned when the portfolio and holding fee frequencies differ.
- If you set fees at both levels, use the same `AnnualFeeFrequency` on the portfolio's `Fees` object and on each holding.
- If you don't need holding-level fees, set the fee on the portfolio only.
See [Errors](/portfolio-xray-api/error-messages) for the specific fee properties each code refers to.
`RequestSettings.HypoCalculationSettings` is required for this request. Add the property to `RequestSettings` and resend the request.
<!-- TODO (author): HypoCalculationSettings is not documented elsewhere in this guide. Confirm when it is required and link to its definition. -->
When holdings use `Weight`:
- Each weight must be between 1 and 100.
- Weights across all holdings in the portfolio must sum to exactly 100. Check for rounding, for example three holdings of `33.33` sum to `99.99`.
- The portfolio must include `TotalValue`.
When holdings use `Value`, the sum of all holding values must equal the portfolio's `TotalValue`. Each value must be at least 1. Recalculate `TotalValue` from the holdings after you add, remove or change any of them.
Every holding in a portfolio must use the same position size type. A portfolio can't mix `Weight` and `Value`, and a holding can't include both. If you have both values available, choose one and use it for every holding in that portfolio.
A request can contain a maximum of 2 portfolios, and each portfolio can contain a maximum of 250 holdings.
- To analyze more than two portfolios, split them across multiple requests.
- To analyze a portfolio with more than 250 positions, consolidate holdings before you submit it.
The portfolio `Currency` and `OutputCurrency` accept only these ISO 4217 codes: `AUD`, `BRL`, `CAD`, `CHF`, `DKK`, `EUR`, `GBP`, `HKD`, `INR`, `JPY`, `MXN`, `MYR`, `NOK`, `NZD`, `SEK`, `SGD`, `TWD`, `USD` and `ZAR`.
If a holding includes more than one identifier, `SecurityId` takes priority. If there's no `SecurityId`, the last identifier listed in the holding is used, which may not be the one you intended. Provide a single identifier per holding.
Trading symbols can be ambiguous across markets. If a symbol resolves to the wrong security, use an ISIN, CUSIP, `SecurityId` or `PerformanceId` instead. Check the `SecurityReference` array in the response to confirm which security each holding resolved to.
By default, invalid and unentitled holdings are dropped and the remaining holdings are rescaled, so the request succeeds without them. To find out which holdings were dropped:
1. Set `DisableRescale` to `true` in `RequestSettings`.
2. Resend the request.
3. Read the `Metadata.InvalidPortfolios` list in the `40059` error. See the `40059` entry under [Request Validation Errors](#request-validation-errors).
After you fix or remove the affected holdings, you can set `DisableRescale` back to `false`.
- **Check the view.** The `View` determines which sections are returned. Omit `View` or set it to `All` to receive every section.
- **Rolling returns.** Add `RollingReturns` to `ReturnDataSections` and set `RollingReturnFrequencies`. Rolling returns aren't returned without both.
- **Correlation matrix.** Add `CorrelationMatrix` to `ReturnDataSections`.
- **Gross and net returns.** Set `IncludeGrossNetReturns` to `true`.
See [Configure an Analysis](/portfolio-xray-api/configure-an-analysis).
The default start date, `EarliestCommon`, is the earliest date for which **all** holdings have return data. A single recently launched holding can therefore shorten the whole analysis.
- Check `PerformanceDate` in the response to see the dates available for the portfolio, including `EarliestInceptionDate`.
- Use `EarliestAvailable` to start from the earliest date for which any holding has data, or `EarliestCommonExtended` to use extended return history where available.
- Use `CustomDate` with `PortfolioPerformanceCustomStartDate` to set the start date yourself.
Each portfolio is analyzed over the period determined by its own holdings, so their start and end dates can differ. Set `SynchronizePortfolioStartDate` and `EnablePerformanceCommonEndDate` to `true` to align them. See [Compare Two Portfolios](/portfolio-xray-api/compare-two-portfolios).
The `XRay` array contains one object per portfolio, identified by `PortfolioName`. Give each portfolio a distinct `Name` in the request, and match on `PortfolioName` rather than on array position.
The asset classes in `AssetAllocation` depend on the asset class group. If you don't set one, the API uses `ACG-USBROAD`. Set `AssetClassGroupConfigs` to the group that matches your market. Only one group can be passed per request. See [Asset Class Group Breakdown](/portfolio-xray-api/asset-class-group-breakdown).
- Output values are calculated in
OutputCurrency, not the portfolio Currency. Set OutputCurrency to the currency you want to report in. - The response language and locale come from the
langcult query parameter, which overrides the Accept-Language header. Supported values are en-US (default), en-CA, en-AU and en-GB.
- Check the Errors page for the full list of error codes.
- Compare your request with the complete example in Request Portfolio X-Ray.
- Browse the FAQs.
- Contact your Morningstar account manager about entitlement or licensing questions.