NocoBase apply-blueprint 栈溢出问题补充材料
1. 完整的 apply-blueprint 请求体(可直接复现)
{
"version": "1",
"mode": "create",
"navigation": {
"group": { "title": "测试成本页面", "icon": "AppstoreOutlined" },
"item": { "title": "测试六步成本核算单", "icon": "InboxOutlined" }
},
"page": { "title": "测试六步成本核算单" },
"tabs": [
{
"key": "main",
"title": "主表",
"blocks": [
{
"key": "mainTable",
"type": "table",
"collection": "costCalculationSheets",
"fields": ["sheetNo", "date", "quotationNo", "pricingMode", "status"],
"actions": ["filter", "refresh"],
"recordActions": ["view", "edit"]
}
]
}
],
"defaults": {
"collections": {
"costCalculationSheets": {
"fieldGroups": [
{ "key": "basic", "title": "基础信息", "fields": ["sheetNo", "date", "quotationNo"] },
{ "key": "rates", "title": "系数", "fields": ["deptMateRate", "deptWorkRate", "outRate", "custRate", "salaryRate"] },
{ "key": "pricing", "title": "定价", "fields": ["pricingMode", "pricingModeInferred"] },
{ "key": "status", "title": "状态", "fields": ["status", "sourceType"] },
{ "key": "time", "title": "时间", "fields": ["createdAt", "updatedAt"] }
]
}
}
}
}
2. 相关集合及 belongsTo 字段结构
2.1 costCalculationSheets(六步成本核算单)
belongsTo 字段:
createdBy → users (FK: createdById)
updatedBy → users (FK: updatedById)
quotations_id → quotations (FK: quotationsIdId)
2.2 quotations(报价单)
belongsTo 字段 (10个):
customers_id → customers
currencies_id → currencies
paymentTerms_id → paymentTerms
shipTypes_id → shipTypes
employees_id → employees
endCustomers_id → endCustomers
costSheets_id → costSheets
silverPrices_id → silverPrices
createdBy → users
updatedBy → users
2.3 customers(客户)
belongsTo 字段 (6个):
customerTypes_id → customerTypes
currencies_id → currencies
paymentTerms_id → paymentTerms
shipTypes_id → shipTypes
createdBy → users
updatedBy → users
2.4 products(产品)
belongsTo 字段 (21个):
- 包含
customers_id, employees_id, departments_id, productCategories_id 等多个关联
2.5 关联链深度示例
costCalculationSheets
→ quotations (多个belongsTo)
→ customers (多个belongsTo)
→ customerTypes, currencies, paymentTerms, shipTypes
→ employees (多个belongsTo)
→ departments
→ costSheets (多个belongsTo)
→ products (多个belongsTo)
→ ... (继续递归)
3. 服务端日志和错误信息
3.1 CLI 错误输出
$ nb api flow-surfaces apply-blueprint --body-file test_blueprint.json -j
[31mRequest failed with status 500
{
"errors": [
{
"message": "Maximum call stack size exceeded",
"type": "internal_error",
"code": "FLOW_SURFACE_INTERNAL_ERROR",
"status": 500
}
]
}
Diagnostic log: [日志文件路径已脱敏]
3.2 服务端日志文件内容
Request failed with status 500
{
"errors": [
{
"message": "Maximum call stack size exceeded",
"type": "internal_error",
"code": "FLOW_SURFACE_INTERNAL_ERROR",
"status": 500
}
]
}
3.3 环境信息
- NocoBase 版本: 2.2.2 (from package.json:
"@nocobase/app": "2.2.2")
- CLI 版本: 2.1.31
- Node.js: v22.23.1
- 操作系统: Linux
- 数据库: PostgreSQL
4. 复现步骤
- 确保数据库中存在
costCalculationSheets 和 quotations 集合,且 quotations 有多个 belongsTo 字段
- 将上面的请求体保存为
test_blueprint.json
- 执行命令:
nb api flow-surfaces apply-blueprint --body-file test_blueprint.json -j
- 观察错误: “Maximum call stack size exceeded”
5. 问题分析
5.1 根本原因
当 apply-blueprint 处理 fieldGroups 时,会递归检查所有 belongsTo 目标表的 fieldGroups。由于关联链过深(costCalculationSheets → quotations → customers → products 等),导致无限递归栈溢出。
5.2 触发条件
- 集合有
belongsTo 关联链(深度 > 3层)
- 在
defaults.collections 中为该集合提供 fieldGroups
- 关联的目标集合也有自己的
belongsTo 关联
5.3 临时解决方案
- 手动在 UI 设计器中搭建页面(不使用 API)
- 或者不提供
fieldGroups(但会导致验证错误)
6. 期望行为
apply-blueprint 应能处理深层 belongsTo 关联链而不栈溢出
- 要么限制递归深度,要么优化
fieldGroups 验证逻辑
- 提供有意义的错误信息,而非通用的栈溢出错误
- 考虑添加递归深度限制或循环引用检测