apollographql / apollographql/vscode-graphql

Multiple definitions for operation hidden error

Open
#252 1 comment 5 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
79
Forks
23
PR merge metrics
No merged PRs in 30d

Description

Originally from https://github.com/apollographql/vscode-graphql/issues/247

When I set up apollo.config.mjs with the extension for the first time I was greeted with a generic abstract error

```
/Users/micfer/.vscode/extensions/apollographql.vscode-apollo-2.5.1/lib/language-server/server.js:1084
`)}t(Dor,"dedentBlockStringValue");function kor(i){let r=null;for(let s=1;s{let u=s.findIndex(_=>_.name.value===c.name.value);return u===-1?s.concat([c]):(r?.reverseArguments||(s[u]=c),s)},[])}t(xor,"deduplicateArguments");function wor(i,r){return!!i.find(s=>s.name.value===r.name.value)}t(wor,"directiveAlreadyExists");function qqt(i,r){return!!r?.[i.name.value]?.repeatable}t(qqt,"isRepeatableDirective");function Vqt(i,r){return r.some(({value:s})=>s===i.value)}t(Vqt,"nameAlreadyExists");function Jqt(i,r){let s=[...r];for(let c of i){let u=s.findIndex(_=>_.name.value===c.name.value);if(u>-1){let _=s[u];if(_.value.kind==="ListValue"){let g=_.value.values,b=c.value.values;_.value.values=Wqt(g,b,(I,w)=>{let L=I.value;return!L||!w.some(V=>V.value===L)})}else _.value=c.value}else s.push(c)}return s}t(Jqt,"mergeArguments");function Nor(i,r){return i.map((s,c,u)=>{let _=u.findIndex(g=>g.name.value===s.name.value);if(_!==c&&!qqt(s,r)){let g=u[_];return s.arguments=Jqt(s.arguments,g.arguments),null}return s}).filter(yz)}t(Nor,"deduplicateDirectives");function iv(i=[],r=[],s,c){let u=s&&s.reverseDirectives,_=u?i:r,g=u?r:i,b=Nor([..._],c);for(let I of g)if(wor(b,I)&&!qqt(I,c)){let w=b.findIndex(V=>V.name.value===I.name.value),L=b[w];b[w].arguments=Jqt(I.arguments||[],L.arguments||[])}else b.push(I);return b}t(iv,"mergeDirectives");function Gqt(i,r){return r?{...i,arguments:Wqt(r.arguments||[],i.arguments||[],(s,c)=>!Vqt(s.name,c.map(u=>u.name))),locations:[...r.locations,...i.locations.filter(s=>!Vqt(s,r.locations))]}:i}t(Gqt,"mergeDirective");function Wqt(i,r,s){return i.concat(r.filter(c=>s(c,i)))}t(Wqt,"deduplicateLists");function Hqt(i,r,s,c){if(s?.consistentEnumMerge){let g=[];i&&g.push(...i),i=r,r=g}let u=new Map;if(i)for(let g of i)u.set(g.name.value,g);if(r)for(let g of r){let b=g.name.value;if(u.has(b)){let I=u.get(b);I.description=g.description||I.description,I.directives=iv(g.directives,I.directives,c)}else u.set(b,g)}let _=[...u.values()];return s&&s.sort&&_.sort(sM),_}t(Hqt,"mergeEnumValues");var zqt=jo(Fo(),1);function $qt(i,r,s,c){return r?{name:i.name,description:i.description||r.description,kind:s?.convertExtensions||i.kind==="EnumTypeDefinition"||r.kind==="EnumTypeDefinition"?"EnumTypeDefinition":"EnumTypeExtension",loc:i.loc,directives:iv(i.directives,r.directives,s,c),values:Hqt(i.values,r.values,s)}:s?.convertExtensions?{...i,kind:zqt.Kind.ENUM_TYPE_DEFINITION}:i}t($qt,"mergeEnum");var d9=jo(Fo(),1);function Yqt(i){return typeof i=="string"}t(Yqt,"isStringTypes");function Kqt(i){return i instanceof d9.Source}t(Kqt,"isSourceTypes");function hXe(i){let r=i;for(;r.kind===d9.Kind.LIST_TYPE||r.kind==="NonNullType";)r=r.type;return r}t(hXe,"extractType");function gXe(i){return i.kind!==d9.Kind.NAMED_TYPE}t(gXe,"isWrappingTypeNode");function FCe(i){return i.kind===d9.Kind.LIST_TYPE}t(FCe,"isListTypeNode");function lM(i){return i.kind===d9.Kind.NON_NULL_TYPE}t(lM,"isNonNullTypeNode");function Lae(i){return FCe(i)?`[${Lae(i.type)}]`:lM(i)?`${Lae(i.type)}!`:i.name.value}t(Lae,"printTypeNode");var cM;(function(i){i[i.A_SMALLER_THAN_B=-1]="A_SMALLER_THAN_B",i[i.A_EQUALS_B=0]="A_EQUALS_B",i[i.A_GREATER_THAN_B=1]="A_GREATER_THAN_B"})(cM||(cM={}));function Xqt(i,r){return i==null&&r==null?cM.A_EQUALS_B:i==null?cM.A_SMALLER_THAN_B:r==null?cM.A_GREATER_THAN_B:ir?cM.A_GREATER_THAN_B:cM.A_EQUALS_B}t(Xqt,"defaultStringComparator");function Por(i,r){let s=i.findIndex(c=>c.name.value===r.name.value);return[s>-1?i[s]:null,s]}t(Por,"fieldAlreadyExists");function Ez(i,r,s,c,u){let _=[];if(s!=null&&_.push(...s),r!=null)for(let g of r){let[b,I]=Por(_,g);if(b&&!c?.ignoreFieldConflicts){let w=c?.onFieldTypeConflict&&c.onFieldTypeConflict(b,g,i,c?.throwOnConflict)||Oor(i,b,g,c?.throwOnConflict);w.arguments=Uqt(g.arguments||[],b.arguments||[],c),w.directives=iv(g.directives,b.directives,c,u),w.description=g.description||b.description,_[I]=w}else _.push(g)}if(c&&c.sort&&_.sort(sM),c&&c.exclusions){let g=c.exclusions;return _.filter(b=>!g.includes(`${i.name.value}.${b.name.value}`))}return _}t(Ez,"mergeFields");function Oor(i,r,s,c=!1){let u=Lae(r.type),_=Lae(s.type);if(u!==_){let g=hXe(r.type),b=hXe(s.type);if(g.name.value!==b.name.value)throw new Error(`Field "${s.name.value}" already defined with a different type. Declared as "${g.name.value}", but you tried to override with "${b.name.value}"`);if(!Mae(r.type,s.type,!c))throw new Error(`Field '${i.name.value}.${r.name.value}' changed type from '${u}' to '${_}'`)}return lM(s.type)&&!lM(r.type)&&(r.type=s.type),r}t(Oor,"preventConflicts");function Mae(i,r,s=!1){if(!gXe(i)&&!gXe(r))return i.toString()===r.toString();if(lM(r)){let c=lM(i)?i.type:i;return Mae(c,r.type)}return lM(i)?Mae(r,i,s):FCe(i)?FCe(r)&&Mae(i.type,r.type)||lM(r)&&Mae(i,r.type):!1}t(Mae,"safeChangeForFieldType");var Zqt=jo(Fo(),1);function eJt(i,r,s,c){if(r)try{return{name:i.name,description:i.description||r.description,kind:s?.convertExtensions||i.kind==="InputObjectTypeDefinition"||r.kind==="InputObjectTypeDefinition"?"InputObjectTypeDefinition":"InputObjectTypeExtension",loc:i.loc,fields:Ez(i,i.fields,r.fields,s),directives:iv(i.directives,r.directives,s,c)}}catch(u){throw new Error(`Unable to merge GraphQL input type "${i.name.value}": ${u.message}`)}return s?.convertExtensions?{...i,kind:Zqt.Kind.INPUT_OBJECT_TYPE_DEFINITION}:i}t(eJt,"mergeInputType");var tJt=jo(Fo(),1);function For(i,r){return!!i.find(s=>s.name.value===r.name.value)}t(For,"alreadyExists");function Sz(i=[],r=[],s={}){let c=[...r,...i.filter(u=>!For(r,u))];return s&&s.sort&&c.sort(sM),c}t(Sz,"mergeNamedTypeArray");function nJt(i,r,s,c){if(r)try{return{name:i.name,description:i.description||r.description,kind:s?.convertExtensions||i.kind==="InterfaceTypeDefinition"||r.kind==="InterfaceTypeDefinition"?"InterfaceTypeDefinition":"InterfaceTypeExtension",loc:i.loc,fields:Ez(i,i.fields,r.fields,s,c),directives:iv(i.directives,r.directives,s,c),interfaces:i.interfaces?Sz(i.interfaces,r.interfaces,s):void 0}}catch(u){throw new Error(`Unable to merge GraphQL interface "${i.name.value}": ${u.message}`)}return s?.convertExtensions?{...i,kind:tJt.Kind.INTERFACE_TYPE_DEFINITION}:i}t(nJt,"mergeInterface");var cb=jo(Fo(),1),lJt=jo(dx(),1);var rJt=jo(Fo(),1);function iJt(i,r,s,c){return r?{name:i.name,description:i.description||r.description,kind:s?.convertExtensions||i.kind==="ScalarTypeDefinition"||r.kind==="ScalarTypeDefinition"?"ScalarTypeDefinition":"ScalarTypeExtension",loc:i.loc,directives:iv(i.directives,r.directives,s,c)}:s?.convertExtensions?{...i,kind:rJt.Kind.SCALAR_TYPE_DEFINITION}:i}t(iJt,"mergeScalar");var Tz=jo(Fo(),1);var RCe={query:"Query",mutation:"Mutation",subscription:"Subscription"};function Ror(i=[],r=[]){let s=[];for(let c in RCe){let u=i.find(_=>_.operation===c)||r.find(_=>_.operation===c);u&&s.push(u)}return s}t(Ror,"mergeOperationTypes");function sJt(i,r,s,c){return r?{kind:i.kind===Tz.Kind.SCHEMA_DEFINITION||r.kind===Tz.Kind.SCHEMA_DEFINITION?Tz.Kind.SCHEMA_DEFINITION:Tz.Kind.SCHEMA_EXTENSION,description:i.description||r.description,directives:iv(i.directives,r.directives,s,c),operationTypes:Ror(i.operationTypes,r.operationTypes)}:s?.convertExtensions?{...i,kind:Tz.Kind.SCHEMA_DEFINITION}:i}t(sJt,"mergeSchemaDefs");var oJt=jo(Fo(),1);function aJt(i,r,s,c){if(r)try{return{name:i.name,description:i.description||r.description,kind:s?.convertExtensions||i.kind==="ObjectTypeDefinition"||r.kind==="ObjectTypeDefinition"?"ObjectTypeDefinition":"ObjectTypeExtension",l[Error - 12:02:36 PM] Server process exited with code 1.
[Info - 12:02:36 PM] Connection to server got closed. Server will restart.
true
```

Then I cloned this repo and launched it in debug and ran it on my project.
I was able to get a clearer error

```
Debugger listening on ws://127.0.0.1:6009/53ca72a0-f97b-4386-99ff-3235f60a6756
For help, see: https://nodejs.org/en/docs/inspector
/Users/micfer/projects/vscode-graphql/lib/language-server/server.js:324152
throw new Error(
^

Error: ️️There are multiple definitions for the `WorkOrderSnapshotQuery` operation. Please fix all naming conflicts before continuing.
Conflicting definitions found at /Users/micfer/projects/maintainx/frontend/src/graphql/queries/WorkOrderDetailsSnapshotQuery.ts and /Users/micfer/projects/maintainx/backend/graphql/src/mutations/helpers/workOrderAssetSnapshot/queries/workOrderSnapshotQuery.ts.
at GraphQLClientProject. (/Users/micfer/projects/vscode-graphql/lib/language-server/server.js:324152:25)
at invokeFunc (/Users/micfer/projects/vscode-graphql/lib/language-server/server.js:307137:23)
at trailingEdge (/Users/micfer/projects/vscode-graphql/lib/language-server/server.js:307168:18)
at Timeout.timerExpired [as _onTimeout] (/Users/micfer/projects/vscode-graphql/lib/language-server/server.js:307160:18)
at listOnTimeout (node:internal/timers:581:17)
at process.processTimers (node:internal/timers:519:7)

Node.js v20.16.0
[Error - 3:42:59 PM] Server process exited with code 1.
[Error - 3:42:59 PM] The Apollo GraphQL server crashed 5 times in the last 3 minutes. The server will not be restarted. See the output for more information.
```

I then realized that in my project I have some duplicated operations that happen to be exactly the same.
Normally I have GraphQL Codegen would catch conflicting operation names, but it seems it detects the 2 operations are exactly the same and let it pass somehow.
I'll have to find some way to detect and error on this on my end.

That being said, I would have expected the extension to
- Not "crash" because of this error
- Report the error in a human readable manner
- Be able to recover after fixing the error without needing to "Reload" VS Code

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the duplicate WorkOrderSnapshotQuery case and inspect the GraphQLClientProject error path in lib/language-server/server.js, including the reported operation-conflict handling. The fix is done when duplicate operations produce a human-readable diagnostic, do not terminate the server, and the extension recovers after the conflict is corrected.

Written by the indexing model from the issue text.

Assessment

Tech stack
graphql, typescript, vscode
Domain
developer-experience, devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.