@netoalmanca/advpl-sensei 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/changelog-generator.md +63 -0
- package/agents/code-generator.md +215 -0
- package/agents/code-reviewer.md +145 -0
- package/agents/debugger.md +83 -0
- package/agents/doc-generator.md +67 -0
- package/agents/docs-reference.md +86 -0
- package/agents/migrator.md +84 -0
- package/agents/process-consultant.md +97 -0
- package/agents/refactorer.md +75 -0
- package/agents/sx-configurator.md +67 -0
- package/commands/changelog.md +66 -0
- package/commands/diagnose.md +67 -0
- package/commands/docs.md +81 -0
- package/commands/document.md +67 -0
- package/commands/explain.md +60 -0
- package/commands/generate.md +111 -0
- package/commands/migrate.md +81 -0
- package/commands/process.md +111 -0
- package/commands/refactor.md +65 -0
- package/commands/review.md +60 -0
- package/commands/sxgen.md +98 -0
- package/commands/test.md +103 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +143 -0
- package/dist/index.js.map +1 -0
- package/package.json +30 -0
- package/skills/advpl-code-generation/SKILL.md +163 -0
- package/skills/advpl-code-generation/patterns-fwformbrowse.md +485 -0
- package/skills/advpl-code-generation/patterns-jobs.md +519 -0
- package/skills/advpl-code-generation/patterns-mvc.md +765 -0
- package/skills/advpl-code-generation/patterns-pontos-entrada.md +708 -0
- package/skills/advpl-code-generation/patterns-rest.md +974 -0
- package/skills/advpl-code-generation/patterns-soap.md +639 -0
- package/skills/advpl-code-generation/patterns-treport.md +481 -0
- package/skills/advpl-code-generation/patterns-workflow.md +779 -0
- package/skills/advpl-code-generation/templates-classes.md +1096 -0
- package/skills/advpl-code-review/SKILL.md +72 -0
- package/skills/advpl-code-review/rules-best-practices.md +444 -0
- package/skills/advpl-code-review/rules-modernization.md +290 -0
- package/skills/advpl-code-review/rules-performance.md +333 -0
- package/skills/advpl-code-review/rules-security.md +302 -0
- package/skills/advpl-debugging/SKILL.md +265 -0
- package/skills/advpl-debugging/common-errors.md +1124 -0
- package/skills/advpl-debugging/performance-tips.md +768 -0
- package/skills/advpl-refactoring/SKILL.md +139 -0
- package/skills/advpl-to-tlpp-migration/SKILL.md +293 -0
- package/skills/advpl-to-tlpp-migration/migration-checklist.md +122 -0
- package/skills/advpl-to-tlpp-migration/migration-rules.md +265 -0
- package/skills/changelog-patterns/SKILL.md +99 -0
- package/skills/code-explanation/SKILL.md +66 -0
- package/skills/documentation-patterns/SKILL.md +172 -0
- package/skills/embedded-sql/SKILL.md +379 -0
- package/skills/probat-testing/SKILL.md +226 -0
- package/skills/probat-testing/patterns-unit-tests.md +614 -0
- package/skills/protheus-business/SKILL.md +92 -0
- package/skills/protheus-business/modulo-compras.md +780 -0
- package/skills/protheus-business/modulo-contabilidade.md +874 -0
- package/skills/protheus-business/modulo-estoque.md +876 -0
- package/skills/protheus-business/modulo-faturamento.md +800 -0
- package/skills/protheus-business/modulo-financeiro.md +1015 -0
- package/skills/protheus-business/modulo-fiscal.md +749 -0
- package/skills/protheus-business/modulo-manutencao.md +848 -0
- package/skills/protheus-business/modulo-pcp.md +743 -0
- package/skills/protheus-reference/SKILL.md +119 -0
- package/skills/protheus-reference/native-functions.md +7029 -0
- package/skills/protheus-reference/rest-api-reference.md +1758 -0
- package/skills/protheus-reference/restricted-functions.md +265 -0
- package/skills/protheus-reference/sx-dictionary.md +854 -0
- package/skills/sx-configuration/SKILL.md +184 -0
|
@@ -0,0 +1,1124 @@
|
|
|
1
|
+
# ADVPL/TLPP Common Errors Reference
|
|
2
|
+
|
|
3
|
+
Top 50 most common ADVPL/TLPP errors organized by category with cause and solution for each.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Compilation Errors
|
|
8
|
+
|
|
9
|
+
### 1. Syntax error at line X / Unexpected token
|
|
10
|
+
|
|
11
|
+
**Error Message:** `Syntax error at line 45: unexpected token 'EndIf'`
|
|
12
|
+
|
|
13
|
+
**Cause:** Mismatched control structures, missing operators, or typos in keywords. Common when mixing uppercase/lowercase keywords or forgetting operators between expressions.
|
|
14
|
+
|
|
15
|
+
**Solution:**
|
|
16
|
+
```advpl
|
|
17
|
+
// WRONG - missing operator
|
|
18
|
+
If cCodCli "001"
|
|
19
|
+
// ...
|
|
20
|
+
EndIf
|
|
21
|
+
|
|
22
|
+
// FIXED - add comparison operator
|
|
23
|
+
If cCodCli == "001"
|
|
24
|
+
// ...
|
|
25
|
+
EndIf
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 2. Variable XXXX already declared
|
|
29
|
+
|
|
30
|
+
**Error Message:** `Variable 'cNome' already declared`
|
|
31
|
+
|
|
32
|
+
**Cause:** Declaring the same variable name twice in the same scope with `Local`, `Static`, or `Private`.
|
|
33
|
+
|
|
34
|
+
**Solution:**
|
|
35
|
+
```advpl
|
|
36
|
+
// WRONG
|
|
37
|
+
Local cNome := ""
|
|
38
|
+
Local cNome := "Test" // duplicate declaration
|
|
39
|
+
|
|
40
|
+
// FIXED - declare once, assign later if needed
|
|
41
|
+
Local cNome := ""
|
|
42
|
+
cNome := "Test"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 3. Function XXXX not found / Undefined function
|
|
46
|
+
|
|
47
|
+
**Error Message:** `Function 'XPTO001' not found`
|
|
48
|
+
|
|
49
|
+
**Cause:** The function does not exist in the RPO, is misspelled, or the source file was not compiled. In TLPP, may also be a missing namespace.
|
|
50
|
+
|
|
51
|
+
**Solution:**
|
|
52
|
+
```advpl
|
|
53
|
+
// Check spelling matches exactly
|
|
54
|
+
// Verify the .prw/.tlpp file is compiled into the RPO
|
|
55
|
+
// If using TLPP with namespaces, ensure the .tlpp file
|
|
56
|
+
// with the class/function is compiled and the caller
|
|
57
|
+
// references the correct namespace via fully qualified name
|
|
58
|
+
// e.g.: custom.vendas.PedidoService():New()
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 4. Missing END / ENDDO / ENDIF
|
|
62
|
+
|
|
63
|
+
**Error Message:** `Missing ENDIF for IF at line 20`
|
|
64
|
+
|
|
65
|
+
**Cause:** Every `If` needs `EndIf`, every `While` needs `EndDo`, every `For` needs `Next`, every `Do Case` needs `EndCase`.
|
|
66
|
+
|
|
67
|
+
**Solution:**
|
|
68
|
+
```advpl
|
|
69
|
+
// WRONG
|
|
70
|
+
If lCondition
|
|
71
|
+
nTotal := 100
|
|
72
|
+
// Missing EndIf
|
|
73
|
+
|
|
74
|
+
// FIXED
|
|
75
|
+
If lCondition
|
|
76
|
+
nTotal := 100
|
|
77
|
+
EndIf
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 5. Missing operator
|
|
81
|
+
|
|
82
|
+
**Error Message:** `Missing operator at line 12`
|
|
83
|
+
|
|
84
|
+
**Cause:** Two expressions placed next to each other without an operator, or a missing concatenation operator (`+`).
|
|
85
|
+
|
|
86
|
+
**Solution:**
|
|
87
|
+
```advpl
|
|
88
|
+
// WRONG
|
|
89
|
+
cMsg := "Total: " cValToChar(nTotal)
|
|
90
|
+
|
|
91
|
+
// FIXED
|
|
92
|
+
cMsg := "Total: " + cValToChar(nTotal)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 6. Type clash in expression
|
|
96
|
+
|
|
97
|
+
**Error Message:** `Type clash in expression at line 30`
|
|
98
|
+
|
|
99
|
+
**Cause:** Attempting to combine incompatible types at compile time. For example, concatenating a string with a numeric literal.
|
|
100
|
+
|
|
101
|
+
**Solution:**
|
|
102
|
+
```advpl
|
|
103
|
+
// WRONG
|
|
104
|
+
cMsg := "Value: " + 100
|
|
105
|
+
|
|
106
|
+
// FIXED
|
|
107
|
+
cMsg := "Value: " + cValToChar(100)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 7. #Include file not found
|
|
111
|
+
|
|
112
|
+
**Error Message:** `#Include file 'MyCustom.ch' not found`
|
|
113
|
+
|
|
114
|
+
**Cause:** The .ch file does not exist in the includes path configured in the Protheus IDE or the filename is misspelled.
|
|
115
|
+
|
|
116
|
+
**Solution:**
|
|
117
|
+
```advpl
|
|
118
|
+
// Verify file exists in the includes directory
|
|
119
|
+
// Check the includes path in your project configuration
|
|
120
|
+
// Standard includes are always available:
|
|
121
|
+
#Include "TOTVS.CH"
|
|
122
|
+
#Include "TopConn.ch"
|
|
123
|
+
#Include "FWMVCDef.ch"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 8. Duplicate function name
|
|
127
|
+
|
|
128
|
+
**Error Message:** `Duplicate definition of function 'FATA001'`
|
|
129
|
+
|
|
130
|
+
**Cause:** Two User Functions with the same name exist in different .prw files compiled into the same RPO.
|
|
131
|
+
|
|
132
|
+
**Solution:**
|
|
133
|
+
```advpl
|
|
134
|
+
// Search your project for duplicate function names
|
|
135
|
+
// Rename one of the functions
|
|
136
|
+
// Use unique module prefix conventions: FATA001, FATA002, etc.
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 9. Too many parameters
|
|
140
|
+
|
|
141
|
+
**Error Message:** `Too many parameters in function call`
|
|
142
|
+
|
|
143
|
+
**Cause:** Passing more arguments to a function than it declares. ADVPL is lenient but TLPP strict mode enforces parameter counts.
|
|
144
|
+
|
|
145
|
+
**Solution:**
|
|
146
|
+
```advpl
|
|
147
|
+
// WRONG - function expects 2 params, called with 4
|
|
148
|
+
Local lRet := MyFunc(cCode, cName, dDate, nVal)
|
|
149
|
+
|
|
150
|
+
// FIXED - match the function signature
|
|
151
|
+
// If extra params are needed, update the function definition
|
|
152
|
+
Static Function MyFunc(cCode, cName, dDate, nVal)
|
|
153
|
+
// ...
|
|
154
|
+
Return lRet
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### 10. Missing RETURN
|
|
158
|
+
|
|
159
|
+
**Error Message:** `Missing RETURN statement in function 'MyFunc'`
|
|
160
|
+
|
|
161
|
+
**Cause:** Every function must end with a `Return` statement. The compiler enforces this.
|
|
162
|
+
|
|
163
|
+
**Solution:**
|
|
164
|
+
```advpl
|
|
165
|
+
// WRONG
|
|
166
|
+
User Function FATA001()
|
|
167
|
+
Local nVal := 10
|
|
168
|
+
// no Return
|
|
169
|
+
|
|
170
|
+
// FIXED
|
|
171
|
+
User Function FATA001()
|
|
172
|
+
Local nVal := 10
|
|
173
|
+
Return nVal
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 11. Invalid character in source
|
|
177
|
+
|
|
178
|
+
**Error Message:** `Invalid character in source at line 5`
|
|
179
|
+
|
|
180
|
+
**Cause:** Non-ASCII characters in the source code outside of string literals (accented characters in variable names, BOM markers, invisible Unicode characters).
|
|
181
|
+
|
|
182
|
+
**Solution:**
|
|
183
|
+
```advpl
|
|
184
|
+
// WRONG
|
|
185
|
+
Local cNúmero := "123" // accented u in variable name
|
|
186
|
+
|
|
187
|
+
// FIXED
|
|
188
|
+
Local cNumero := "123" // ASCII only for identifiers
|
|
189
|
+
// Accented characters are fine inside strings:
|
|
190
|
+
Local cMsg := "Numero do documento"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### 12. Ambiguous reference
|
|
194
|
+
|
|
195
|
+
**Error Message:** `Ambiguous reference to 'cValue'`
|
|
196
|
+
|
|
197
|
+
**Cause:** A variable exists in multiple scopes (e.g., Local and Private) creating ambiguity. Also occurs with field names conflicting with variable names.
|
|
198
|
+
|
|
199
|
+
**Solution:**
|
|
200
|
+
```advpl
|
|
201
|
+
// WRONG - cValue exists as both Local and field
|
|
202
|
+
Local cValue := ""
|
|
203
|
+
cValue := SA1->A1_NOME // ambiguous if there is a field called cValue
|
|
204
|
+
|
|
205
|
+
// FIXED - use explicit alias for field references
|
|
206
|
+
// and prefix variables properly
|
|
207
|
+
Local cNome := ""
|
|
208
|
+
cNome := SA1->A1_NOME
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### 13. Missing #Include "TOTVS.CH"
|
|
212
|
+
|
|
213
|
+
**Error Message:** `Undefined symbol 'PSAY'` or `Syntax error` on standard macros
|
|
214
|
+
|
|
215
|
+
**Cause:** TOTVS.CH (formerly Protheus.ch, which is now obsolete) defines essential preprocessor macros (@ ... SAY, @ ... GET, DEFINE DIALOG, etc.). Without it, these commands are not recognized.
|
|
216
|
+
|
|
217
|
+
**Solution:**
|
|
218
|
+
```advpl
|
|
219
|
+
// WRONG - missing include causes many cryptic errors
|
|
220
|
+
User Function FATA001()
|
|
221
|
+
@ 10,10 Say "Hello" // error: undefined syntax
|
|
222
|
+
Return
|
|
223
|
+
|
|
224
|
+
// FIXED - always include as first line
|
|
225
|
+
#Include "TOTVS.CH"
|
|
226
|
+
|
|
227
|
+
User Function FATA001()
|
|
228
|
+
@ 10,10 Say "Hello"
|
|
229
|
+
Return
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### 14. Invalid preprocessor directive
|
|
233
|
+
|
|
234
|
+
**Error Message:** `Invalid preprocessor directive '#DEFINEE'`
|
|
235
|
+
|
|
236
|
+
**Cause:** Typo in preprocessor command. Valid directives: `#Include`, `#Define`, `#IfDef`, `#IfNDef`, `#Else`, `#EndIf`, `#xCommand`, `#xTranslate`.
|
|
237
|
+
|
|
238
|
+
**Solution:**
|
|
239
|
+
```advpl
|
|
240
|
+
// WRONG
|
|
241
|
+
#Definee MAX_SIZE 100
|
|
242
|
+
|
|
243
|
+
// FIXED
|
|
244
|
+
#Define MAX_SIZE 100
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### 15. Class/Method not found (TLPP)
|
|
248
|
+
|
|
249
|
+
**Error Message:** `Class 'MyService' not found` or `Method 'getData' not found in class`
|
|
250
|
+
|
|
251
|
+
**Cause:** In TLPP, classes require proper namespace declaration and `Using Namespace` in the consumer file. Method must be declared in the class definition.
|
|
252
|
+
|
|
253
|
+
**Solution:**
|
|
254
|
+
```tlpp
|
|
255
|
+
// Class definition
|
|
256
|
+
Namespace mycompany.services
|
|
257
|
+
|
|
258
|
+
Class MyService
|
|
259
|
+
Public Method New() As Object
|
|
260
|
+
Public Method getData() As Array
|
|
261
|
+
EndClass
|
|
262
|
+
|
|
263
|
+
// Consumer file
|
|
264
|
+
#Include "TOTVS.CH"
|
|
265
|
+
Using Namespace mycompany.services
|
|
266
|
+
|
|
267
|
+
User Function TestSvc()
|
|
268
|
+
Local oSvc := MyService():New()
|
|
269
|
+
Local aData := oSvc:getData()
|
|
270
|
+
Return
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Runtime Errors
|
|
276
|
+
|
|
277
|
+
### 16. Variable does not exist
|
|
278
|
+
|
|
279
|
+
**Error Message:** `Error: Variable 'CCODCLI' does not exist`
|
|
280
|
+
|
|
281
|
+
**Cause:** Referencing a variable that was never declared with `Local`, `Static`, `Private`, or `Public`. Often a typo in the variable name.
|
|
282
|
+
|
|
283
|
+
**Solution:**
|
|
284
|
+
```advpl
|
|
285
|
+
// WRONG
|
|
286
|
+
User Function FATA001()
|
|
287
|
+
cCodCli := "000001" // not declared
|
|
288
|
+
Return
|
|
289
|
+
|
|
290
|
+
// FIXED
|
|
291
|
+
User Function FATA001()
|
|
292
|
+
Local cCodCli := "000001"
|
|
293
|
+
Return
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### 17. Array access out of bounds (index N of N)
|
|
297
|
+
|
|
298
|
+
**Error Message:** `Array access error: index 5 of 3`
|
|
299
|
+
|
|
300
|
+
**Cause:** Trying to access an array position that does not exist. Index is greater than `Len(aArray)` or less than 1.
|
|
301
|
+
|
|
302
|
+
**Solution:**
|
|
303
|
+
```advpl
|
|
304
|
+
// WRONG - no bounds check
|
|
305
|
+
Local aItems := {"A", "B", "C"}
|
|
306
|
+
cVal := aItems[5] // only 3 elements
|
|
307
|
+
|
|
308
|
+
// FIXED - always check bounds
|
|
309
|
+
Local aItems := {"A", "B", "C"}
|
|
310
|
+
If Len(aItems) >= 5
|
|
311
|
+
cVal := aItems[5]
|
|
312
|
+
Else
|
|
313
|
+
Conout("Index out of bounds. Array size: " + cValToChar(Len(aItems)))
|
|
314
|
+
EndIf
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### 18. Type mismatch on operation
|
|
318
|
+
|
|
319
|
+
**Error Message:** `Type mismatch on + : C and N`
|
|
320
|
+
|
|
321
|
+
**Cause:** Performing an operation between incompatible types, such as adding a string to a number.
|
|
322
|
+
|
|
323
|
+
**Solution:**
|
|
324
|
+
```advpl
|
|
325
|
+
// WRONG
|
|
326
|
+
Local cMsg := "Total: " + nTotal // string + numeric
|
|
327
|
+
|
|
328
|
+
// FIXED - convert to same type
|
|
329
|
+
Local cMsg := "Total: " + cValToChar(nTotal)
|
|
330
|
+
|
|
331
|
+
// Or for numeric operations, ensure both are numeric:
|
|
332
|
+
Local nResult := Val(cNumStr) + nTotal
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### 19. Divide by zero
|
|
336
|
+
|
|
337
|
+
**Error Message:** `Divide by zero`
|
|
338
|
+
|
|
339
|
+
**Cause:** Dividing a number by zero without a guard check.
|
|
340
|
+
|
|
341
|
+
**Solution:**
|
|
342
|
+
```advpl
|
|
343
|
+
// WRONG
|
|
344
|
+
nPerc := nParcial / nTotal // nTotal might be 0
|
|
345
|
+
|
|
346
|
+
// FIXED - guard against zero
|
|
347
|
+
If nTotal != 0
|
|
348
|
+
nPerc := nParcial / nTotal
|
|
349
|
+
Else
|
|
350
|
+
nPerc := 0
|
|
351
|
+
EndIf
|
|
352
|
+
|
|
353
|
+
// Alternative - inline with NoRound or IIf
|
|
354
|
+
nPerc := IIf(nTotal > 0, nParcial / nTotal, 0)
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### 20. NIL value in expression
|
|
358
|
+
|
|
359
|
+
**Error Message:** `Value is NIL` or `Type mismatch: U and C`
|
|
360
|
+
|
|
361
|
+
**Cause:** Using a variable that has not been initialized (defaults to NIL) or a function returned NIL unexpectedly.
|
|
362
|
+
|
|
363
|
+
**Solution:**
|
|
364
|
+
```advpl
|
|
365
|
+
// WRONG
|
|
366
|
+
Local cResult
|
|
367
|
+
cMsg := "Result: " + cResult // cResult is NIL
|
|
368
|
+
|
|
369
|
+
// FIXED - always initialize
|
|
370
|
+
Local cResult := ""
|
|
371
|
+
cMsg := "Result: " + cResult
|
|
372
|
+
|
|
373
|
+
// Or guard with ValType check
|
|
374
|
+
If ValType(cResult) == "C"
|
|
375
|
+
cMsg := "Result: " + cResult
|
|
376
|
+
EndIf
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### 21. Invalid alias XXXX
|
|
380
|
+
|
|
381
|
+
**Error Message:** `Invalid alias 'SA1'`
|
|
382
|
+
|
|
383
|
+
**Cause:** Attempting to access a workarea/alias that has not been opened or has been closed.
|
|
384
|
+
|
|
385
|
+
**Solution:**
|
|
386
|
+
```advpl
|
|
387
|
+
// WRONG - alias not opened
|
|
388
|
+
cNome := SA1->A1_NOME
|
|
389
|
+
|
|
390
|
+
// FIXED - open the workarea first
|
|
391
|
+
DbSelectArea("SA1")
|
|
392
|
+
DbSetOrder(1)
|
|
393
|
+
If DbSeek(xFilial("SA1") + cCodCli)
|
|
394
|
+
cNome := SA1->A1_NOME
|
|
395
|
+
EndIf
|
|
396
|
+
|
|
397
|
+
// Or check if alias is active:
|
|
398
|
+
If Select("SA1") > 0
|
|
399
|
+
cNome := SA1->A1_NOME
|
|
400
|
+
EndIf
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### 22. WorkArea not in use
|
|
404
|
+
|
|
405
|
+
**Error Message:** `WorkArea not in use`
|
|
406
|
+
|
|
407
|
+
**Cause:** The alias was closed (via `DbCloseArea()`) or was never opened, but code still tries to navigate or read from it.
|
|
408
|
+
|
|
409
|
+
**Solution:**
|
|
410
|
+
```advpl
|
|
411
|
+
// WRONG - area closed before usage
|
|
412
|
+
DbSelectArea("QRY_TMP")
|
|
413
|
+
DbCloseArea()
|
|
414
|
+
// ... later ...
|
|
415
|
+
QRY_TMP->FIELD1 // WorkArea not in use
|
|
416
|
+
|
|
417
|
+
// FIXED - check before using
|
|
418
|
+
If Select("QRY_TMP") > 0
|
|
419
|
+
cVal := QRY_TMP->FIELD1
|
|
420
|
+
DbSelectArea("QRY_TMP")
|
|
421
|
+
DbCloseArea()
|
|
422
|
+
EndIf
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### 23. RecLock timeout
|
|
426
|
+
|
|
427
|
+
**Error Message:** `Record lock timeout on alias 'SD1'`
|
|
428
|
+
|
|
429
|
+
**Cause:** Another user or thread holds a lock on the same record, and the timeout expired.
|
|
430
|
+
|
|
431
|
+
**Solution:**
|
|
432
|
+
```advpl
|
|
433
|
+
// WRONG - blocks indefinitely
|
|
434
|
+
RecLock("SD1", .T.)
|
|
435
|
+
SD1->D1_TOTAL := nVal
|
|
436
|
+
MsUnlock()
|
|
437
|
+
|
|
438
|
+
// FIXED - use non-blocking lock with retry
|
|
439
|
+
Local nRetries := 3
|
|
440
|
+
Local lLocked := .F.
|
|
441
|
+
|
|
442
|
+
While nRetries > 0 .And. !lLocked
|
|
443
|
+
lLocked := RecLock("SD1", .F.)
|
|
444
|
+
If !lLocked
|
|
445
|
+
nRetries--
|
|
446
|
+
Sleep(1000) // wait 1 second before retry
|
|
447
|
+
EndIf
|
|
448
|
+
EndDo
|
|
449
|
+
|
|
450
|
+
If lLocked
|
|
451
|
+
SD1->D1_TOTAL := nVal
|
|
452
|
+
MsUnlock()
|
|
453
|
+
Else
|
|
454
|
+
Conout("ERROR: Unable to lock record after retries")
|
|
455
|
+
EndIf
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### 24. Code block evaluation error
|
|
459
|
+
|
|
460
|
+
**Error Message:** `Error evaluating code block`
|
|
461
|
+
|
|
462
|
+
**Cause:** The code block references variables that are out of scope, or contains a runtime error within the block.
|
|
463
|
+
|
|
464
|
+
**Solution:**
|
|
465
|
+
```advpl
|
|
466
|
+
// WRONG - variable cField not available when block executes
|
|
467
|
+
Static Function CreateBlock()
|
|
468
|
+
Local cField := "A1_NOME"
|
|
469
|
+
Return {|| &cField } // macro may fail at eval time
|
|
470
|
+
|
|
471
|
+
// FIXED - capture value inside the block
|
|
472
|
+
Static Function CreateBlock()
|
|
473
|
+
Local cField := "A1_NOME"
|
|
474
|
+
Return {|| SA1->&(cField) }
|
|
475
|
+
|
|
476
|
+
// Or avoid macro entirely:
|
|
477
|
+
Static Function GetFieldValue(cAlias, cField)
|
|
478
|
+
Local xVal := (cAlias)->&(cField)
|
|
479
|
+
Return xVal
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### 25. Object method not found
|
|
483
|
+
|
|
484
|
+
**Error Message:** `Method 'PROCESS' not found in object of class 'TFONTS'`
|
|
485
|
+
|
|
486
|
+
**Cause:** Calling a method that does not exist on the object, or the object is of a different class than expected.
|
|
487
|
+
|
|
488
|
+
**Solution:**
|
|
489
|
+
```advpl
|
|
490
|
+
// Debug - check object class
|
|
491
|
+
Conout("Class: " + GetClassName(oObj))
|
|
492
|
+
|
|
493
|
+
// WRONG - calling wrong method
|
|
494
|
+
oObj:Process() // method does not exist
|
|
495
|
+
|
|
496
|
+
// FIXED - check method exists or use correct class
|
|
497
|
+
If FindMember(oObj, "Process")
|
|
498
|
+
oObj:Process()
|
|
499
|
+
Else
|
|
500
|
+
Conout("Method Process not found on " + GetClassName(oObj))
|
|
501
|
+
EndIf
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### 26. Stack overflow
|
|
505
|
+
|
|
506
|
+
**Error Message:** `Stack overflow` or `Internal error: stack limit exceeded`
|
|
507
|
+
|
|
508
|
+
**Cause:** Infinite recursion or extremely deep call chains. A function calls itself without a proper base case.
|
|
509
|
+
|
|
510
|
+
**Solution:**
|
|
511
|
+
```advpl
|
|
512
|
+
// WRONG - infinite recursion
|
|
513
|
+
Static Function Factorial(n)
|
|
514
|
+
Return n * Factorial(n - 1) // never stops when n <= 0
|
|
515
|
+
|
|
516
|
+
// FIXED - add base case
|
|
517
|
+
Static Function Factorial(n)
|
|
518
|
+
If n <= 1
|
|
519
|
+
Return 1
|
|
520
|
+
EndIf
|
|
521
|
+
Return n * Factorial(n - 1)
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### 27. Memory allocation error
|
|
525
|
+
|
|
526
|
+
**Error Message:** `Memory allocation error` or `Out of memory`
|
|
527
|
+
|
|
528
|
+
**Cause:** Arrays growing without bounds, large string concatenations, or unclosed workareas consuming resources.
|
|
529
|
+
|
|
530
|
+
**Solution:**
|
|
531
|
+
```advpl
|
|
532
|
+
// WRONG - unbounded array growth
|
|
533
|
+
Local aData := {}
|
|
534
|
+
While .T. // endless loop
|
|
535
|
+
aAdd(aData, GetRecord())
|
|
536
|
+
EndDo
|
|
537
|
+
|
|
538
|
+
// FIXED - add limits and cleanup
|
|
539
|
+
Local aData := {}
|
|
540
|
+
Local nLimit := 10000
|
|
541
|
+
While !Eof() .And. Len(aData) < nLimit
|
|
542
|
+
aAdd(aData, GetRecord())
|
|
543
|
+
DbSkip()
|
|
544
|
+
EndDo
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### 28. String too long
|
|
548
|
+
|
|
549
|
+
**Error Message:** `String too long` or truncation issues
|
|
550
|
+
|
|
551
|
+
**Cause:** ADVPL strings have a maximum size limit. Repeated concatenation in a loop can exceed it.
|
|
552
|
+
|
|
553
|
+
**Solution:**
|
|
554
|
+
```advpl
|
|
555
|
+
// WRONG - builds massive string in loop
|
|
556
|
+
Local cHtml := ""
|
|
557
|
+
While !Eof()
|
|
558
|
+
cHtml += "<tr><td>" + ALIAS->FIELD1 + "</td></tr>"
|
|
559
|
+
DbSkip()
|
|
560
|
+
EndDo
|
|
561
|
+
|
|
562
|
+
// FIXED - use array and join at the end
|
|
563
|
+
Local aHtml := {}
|
|
564
|
+
While !Eof()
|
|
565
|
+
aAdd(aHtml, "<tr><td>" + ALIAS->FIELD1 + "</td></tr>")
|
|
566
|
+
DbSkip()
|
|
567
|
+
EndDo
|
|
568
|
+
cHtml := ArrTokStr(aHtml, CRLF)
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### 29. Date conversion error (invalid date)
|
|
572
|
+
|
|
573
|
+
**Error Message:** `Invalid date` or wrong date returned
|
|
574
|
+
|
|
575
|
+
**Cause:** Using `StoD()` with an incorrectly formatted string (expected YYYYMMDD), or `CtoD()` with wrong date format.
|
|
576
|
+
|
|
577
|
+
**Solution:**
|
|
578
|
+
```advpl
|
|
579
|
+
// WRONG
|
|
580
|
+
Local dDate := StoD("01/01/2024") // StoD expects YYYYMMDD
|
|
581
|
+
|
|
582
|
+
// FIXED
|
|
583
|
+
Local dDate := StoD("20240101") // correct format for StoD
|
|
584
|
+
Local dDate2 := CtoD("01/01/2024") // CtoD uses system date format
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### 30. Numeric overflow
|
|
588
|
+
|
|
589
|
+
**Error Message:** `Numeric overflow`
|
|
590
|
+
|
|
591
|
+
**Cause:** A numeric value exceeds the maximum precision defined for a field or variable. Often occurs when writing to a database field with limited size (e.g., N(10,2)).
|
|
592
|
+
|
|
593
|
+
**Solution:**
|
|
594
|
+
```advpl
|
|
595
|
+
// WRONG - value exceeds field precision
|
|
596
|
+
SD1->D1_TOTAL := 99999999999.99 // field is N(14,2) - too large
|
|
597
|
+
|
|
598
|
+
// FIXED - validate before writing
|
|
599
|
+
If nTotal <= 99999999999.99 .And. nTotal >= -99999999999.99
|
|
600
|
+
SD1->D1_TOTAL := nTotal
|
|
601
|
+
Else
|
|
602
|
+
Conout("ERROR: Numeric overflow for D1_TOTAL: " + cValToChar(nTotal))
|
|
603
|
+
EndIf
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
### 31. Invalid function argument
|
|
607
|
+
|
|
608
|
+
**Error Message:** `Invalid argument passed to function 'SubStr'`
|
|
609
|
+
|
|
610
|
+
**Cause:** Passing NIL or wrong type to a native function that expects a specific type.
|
|
611
|
+
|
|
612
|
+
**Solution:**
|
|
613
|
+
```advpl
|
|
614
|
+
// WRONG - first param is NIL
|
|
615
|
+
Local cResult := SubStr(cText, 1, 5) // cText might be NIL
|
|
616
|
+
|
|
617
|
+
// FIXED - validate before calling
|
|
618
|
+
If ValType(cText) == "C" .And. !Empty(cText)
|
|
619
|
+
cResult := SubStr(cText, 1, Min(5, Len(cText)))
|
|
620
|
+
Else
|
|
621
|
+
cResult := ""
|
|
622
|
+
EndIf
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
### 32. Thread error
|
|
626
|
+
|
|
627
|
+
**Error Message:** `Thread creation error` or `Maximum number of threads exceeded`
|
|
628
|
+
|
|
629
|
+
**Cause:** Too many concurrent threads created, or the AppServer thread pool is exhausted.
|
|
630
|
+
|
|
631
|
+
**Solution:**
|
|
632
|
+
```advpl
|
|
633
|
+
// Check appserver.ini for MaxThreads setting
|
|
634
|
+
// [General]
|
|
635
|
+
// MaxThreads=200
|
|
636
|
+
|
|
637
|
+
// WRONG - creating threads without limit
|
|
638
|
+
For nI := 1 To 10000
|
|
639
|
+
StartJob("U_PROCESS", cEnvServer, .F., nI)
|
|
640
|
+
Next
|
|
641
|
+
|
|
642
|
+
// FIXED - control concurrency
|
|
643
|
+
Local nMaxThreads := 10
|
|
644
|
+
Local nActive := 0
|
|
645
|
+
For nI := 1 To nTotal
|
|
646
|
+
While nActive >= nMaxThreads
|
|
647
|
+
Sleep(500)
|
|
648
|
+
// Check for completed threads
|
|
649
|
+
EndDo
|
|
650
|
+
StartJob("U_PROCESS", cEnvServer, .F., nI)
|
|
651
|
+
nActive++
|
|
652
|
+
Next
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
### 33. DLL load failure
|
|
656
|
+
|
|
657
|
+
**Error Message:** `Error loading DLL: 'mylib.dll'`
|
|
658
|
+
|
|
659
|
+
**Cause:** The DLL does not exist in the expected path, is not compatible (32/64 bit mismatch), or has missing dependencies.
|
|
660
|
+
|
|
661
|
+
**Solution:**
|
|
662
|
+
```advpl
|
|
663
|
+
// Verify DLL exists in the AppServer directory or system PATH
|
|
664
|
+
// Check 32-bit vs 64-bit compatibility with AppServer
|
|
665
|
+
// Use ExeDllRun2/ExeDllRun3 with full path:
|
|
666
|
+
Local nHandle := ExeDllRun2("C:\TOTVS\bin\appserver\mylib.dll", "MyFunction")
|
|
667
|
+
If nHandle < 0
|
|
668
|
+
Conout("ERROR: DLL load failed. Verify path and architecture.")
|
|
669
|
+
EndIf
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
### 34. Connection refused (DB)
|
|
673
|
+
|
|
674
|
+
**Error Message:** `Connection refused` or `Cannot connect to database server`
|
|
675
|
+
|
|
676
|
+
**Cause:** The database server (SQL Server, PostgreSQL, Oracle) is unreachable due to network issues, wrong credentials, or the database service is down.
|
|
677
|
+
|
|
678
|
+
**Solution:**
|
|
679
|
+
```advpl
|
|
680
|
+
// Check dbaccess.ini / appserver.ini settings:
|
|
681
|
+
// [DBAccess]
|
|
682
|
+
// DBDataBase=MSSQL
|
|
683
|
+
// DBServer=localhost
|
|
684
|
+
// DBPort=7890
|
|
685
|
+
|
|
686
|
+
// In code - check connection before operations:
|
|
687
|
+
If !TCSqlExec("SELECT 1") == 0
|
|
688
|
+
Conout("ERROR: Database connection failed")
|
|
689
|
+
Conout("Check DBAccess configuration and network connectivity")
|
|
690
|
+
EndIf
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
### 35. Encoding/charset error
|
|
694
|
+
|
|
695
|
+
**Error Message:** `Character conversion error` or garbled text in output
|
|
696
|
+
|
|
697
|
+
**Cause:** Mismatch between the source file encoding, the Protheus environment encoding, and the database encoding. Common when mixing Latin1 and UTF-8.
|
|
698
|
+
|
|
699
|
+
**Solution:**
|
|
700
|
+
```advpl
|
|
701
|
+
// Check environment encoding in appserver.ini:
|
|
702
|
+
// [General]
|
|
703
|
+
// SourceEncoding=CP1252
|
|
704
|
+
|
|
705
|
+
// For explicit conversion:
|
|
706
|
+
Local cUtf8Text := EncodeUTF8(cAnsiText)
|
|
707
|
+
Local cAnsiText := DecodeUTF8(cUtf8Text)
|
|
708
|
+
|
|
709
|
+
// For REST APIs that require UTF-8:
|
|
710
|
+
oRest:SetContentType("application/json; charset=utf-8")
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
715
|
+
## Database Errors
|
|
716
|
+
|
|
717
|
+
### 36. Table/alias not found
|
|
718
|
+
|
|
719
|
+
**Error Message:** `Alias 'ZA1' not found` or `Table ZA1010 does not exist`
|
|
720
|
+
|
|
721
|
+
**Cause:** The table is not registered in SX2, or the physical table was not created in the database.
|
|
722
|
+
|
|
723
|
+
**Solution:**
|
|
724
|
+
```advpl
|
|
725
|
+
// Check if table exists in SX2
|
|
726
|
+
DbSelectArea("SX2")
|
|
727
|
+
DbSetOrder(1)
|
|
728
|
+
If !DbSeek("ZA1")
|
|
729
|
+
Conout("Table ZA1 not found in SX2. Run UPDDISTR or add via configurator.")
|
|
730
|
+
EndIf
|
|
731
|
+
|
|
732
|
+
// If table exists in SX2 but not in DB, run:
|
|
733
|
+
// APSDU > Create Table or use TCGenQry to verify
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### 37. Index not found / Invalid order
|
|
737
|
+
|
|
738
|
+
**Error Message:** `Invalid order number 4 for alias 'SA1'`
|
|
739
|
+
|
|
740
|
+
**Cause:** Calling `DbSetOrder(N)` with an order number that does not exist in the SIX index table for this alias.
|
|
741
|
+
|
|
742
|
+
**Solution:**
|
|
743
|
+
```advpl
|
|
744
|
+
// WRONG
|
|
745
|
+
DbSelectArea("SA1")
|
|
746
|
+
DbSetOrder(15) // order 15 does not exist for SA1
|
|
747
|
+
|
|
748
|
+
// FIXED - verify available indexes
|
|
749
|
+
// Check SIX table for SA1 entries
|
|
750
|
+
// Use IndexOrd() to check current order
|
|
751
|
+
DbSelectArea("SA1")
|
|
752
|
+
If IndexOrd() == 0
|
|
753
|
+
Conout("No indexes available for SA1")
|
|
754
|
+
EndIf
|
|
755
|
+
DbSetOrder(1) // use a known valid index
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
### 38. Record lock timeout
|
|
759
|
+
|
|
760
|
+
**Error Message:** `Lock timeout on record 12345 of alias 'SC5'`
|
|
761
|
+
|
|
762
|
+
**Cause:** Extended lock held by another thread, often from a long transaction or user leaving a record open for editing.
|
|
763
|
+
|
|
764
|
+
**Solution:**
|
|
765
|
+
```advpl
|
|
766
|
+
// Monitor locks using Protheus Monitor (SIGAMNT)
|
|
767
|
+
// Or via AppServer console: check active threads
|
|
768
|
+
|
|
769
|
+
// Programmatic approach:
|
|
770
|
+
If RecLock("SC5", .F.)
|
|
771
|
+
// perform update
|
|
772
|
+
MsUnlock()
|
|
773
|
+
Else
|
|
774
|
+
FWLogMsg("WARNING", , "LOCKMON", "MyModule", "", 01, ;
|
|
775
|
+
"Lock timeout on SC5 RecNo: " + cValToChar(RecNo()))
|
|
776
|
+
EndIf
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### 39. Transaction error
|
|
780
|
+
|
|
781
|
+
**Error Message:** `Transaction commit failed` or `Transaction already active`
|
|
782
|
+
|
|
783
|
+
**Cause:** Nesting `Begin Transaction` without proper `End Transaction`, or a transaction left open after an error.
|
|
784
|
+
|
|
785
|
+
**Solution:**
|
|
786
|
+
```advpl
|
|
787
|
+
// WRONG - nested transactions without control
|
|
788
|
+
Begin Transaction
|
|
789
|
+
Begin Transaction // already in transaction
|
|
790
|
+
RecLock("SA1", .F.)
|
|
791
|
+
SA1->A1_NOME := "Test"
|
|
792
|
+
MsUnlock()
|
|
793
|
+
End Transaction
|
|
794
|
+
End Transaction
|
|
795
|
+
|
|
796
|
+
// FIXED - single transaction scope
|
|
797
|
+
Begin Transaction
|
|
798
|
+
RecLock("SA1", .F.)
|
|
799
|
+
SA1->A1_NOME := "Test"
|
|
800
|
+
MsUnlock()
|
|
801
|
+
|
|
802
|
+
RecLock("SA2", .F.)
|
|
803
|
+
SA2->A2_NOME := "Test"
|
|
804
|
+
MsUnlock()
|
|
805
|
+
End Transaction
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
### 40. SQL syntax error (embedded query)
|
|
809
|
+
|
|
810
|
+
**Error Message:** `SQL syntax error near '...'`
|
|
811
|
+
|
|
812
|
+
**Cause:** Malformed embedded SQL query, missing quotes, wrong table name, or database-specific syntax issues.
|
|
813
|
+
|
|
814
|
+
**Solution:**
|
|
815
|
+
```advpl
|
|
816
|
+
// WRONG - missing quotes around string value
|
|
817
|
+
Local cQuery := "SELECT * FROM " + RetSqlName("SA1") + " WHERE A1_COD = " + cCodCli
|
|
818
|
+
|
|
819
|
+
// FIXED - proper quoting
|
|
820
|
+
Local cQuery := "SELECT * FROM " + RetSqlName("SA1") + " SA1 "
|
|
821
|
+
cQuery += "WHERE A1_FILIAL = '" + xFilial("SA1") + "' "
|
|
822
|
+
cQuery += "AND A1_COD = '" + cCodCli + "' "
|
|
823
|
+
cQuery += "AND SA1.D_E_L_E_T_ = ' ' "
|
|
824
|
+
|
|
825
|
+
// Always include D_E_L_E_T_ filter
|
|
826
|
+
// Always use RetSqlName() for table names
|
|
827
|
+
TCQuery cQuery New Alias "QRY_SA1"
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
### 41. Connection lost
|
|
831
|
+
|
|
832
|
+
**Error Message:** `Connection to database lost` or `DBAccess communication failure`
|
|
833
|
+
|
|
834
|
+
**Cause:** Network interruption, database server restart, or DBAccess timeout.
|
|
835
|
+
|
|
836
|
+
**Solution:**
|
|
837
|
+
```advpl
|
|
838
|
+
// Implement retry logic for critical operations
|
|
839
|
+
Local nRetries := 3
|
|
840
|
+
Local lOk := .F.
|
|
841
|
+
|
|
842
|
+
While nRetries > 0 .And. !lOk
|
|
843
|
+
If TCSqlExec("SELECT 1") == 0
|
|
844
|
+
lOk := .T.
|
|
845
|
+
Else
|
|
846
|
+
nRetries--
|
|
847
|
+
Conout("DB connection lost. Retrying... (" + cValToChar(nRetries) + " left)")
|
|
848
|
+
Sleep(2000)
|
|
849
|
+
TCSqlReconnect() // attempt reconnection
|
|
850
|
+
EndIf
|
|
851
|
+
EndDo
|
|
852
|
+
|
|
853
|
+
If !lOk
|
|
854
|
+
FWLogMsg("ERROR", , "DBCONN", "MyModule", "", 01, "Database connection unrecoverable")
|
|
855
|
+
EndIf
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
### 42. Deadlock detected
|
|
859
|
+
|
|
860
|
+
**Error Message:** `Deadlock detected` or `Transaction was deadlocked`
|
|
861
|
+
|
|
862
|
+
**Cause:** Two or more threads lock resources in opposite order, creating a circular wait.
|
|
863
|
+
|
|
864
|
+
**Solution:**
|
|
865
|
+
```advpl
|
|
866
|
+
// WRONG - Thread 1 locks SA1 then SC5, Thread 2 locks SC5 then SA1
|
|
867
|
+
// Thread 1:
|
|
868
|
+
RecLock("SA1", .F.)
|
|
869
|
+
RecLock("SC5", .F.) // deadlock if Thread 2 holds SC5
|
|
870
|
+
|
|
871
|
+
// FIXED - always lock in consistent alphabetical order
|
|
872
|
+
// Thread 1 and Thread 2 both lock SA1 first, then SC5
|
|
873
|
+
RecLock("SA1", .F.)
|
|
874
|
+
RecLock("SC5", .F.)
|
|
875
|
+
// ... operations ...
|
|
876
|
+
MsUnlock()
|
|
877
|
+
DbSelectArea("SA1")
|
|
878
|
+
MsUnlock()
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
### 43. Exclusive lock required
|
|
882
|
+
|
|
883
|
+
**Error Message:** `Exclusive lock required for operation on 'SA1'`
|
|
884
|
+
|
|
885
|
+
**Cause:** Operations like PACK, ZAP, or index rebuild require exclusive table access, but shared locks exist.
|
|
886
|
+
|
|
887
|
+
**Solution:**
|
|
888
|
+
```advpl
|
|
889
|
+
// These operations need exclusive access:
|
|
890
|
+
// - DbPack()
|
|
891
|
+
// - DbZap()
|
|
892
|
+
// - Index rebuild
|
|
893
|
+
|
|
894
|
+
// Schedule during maintenance window when no users are connected
|
|
895
|
+
// Or use DBAccess admin tools for index rebuilding
|
|
896
|
+
|
|
897
|
+
// In code, check for exclusive access:
|
|
898
|
+
If FLock() // try to lock entire file
|
|
899
|
+
DbPack()
|
|
900
|
+
DbUnlock()
|
|
901
|
+
Else
|
|
902
|
+
Conout("Cannot obtain exclusive lock on table. Users may be connected.")
|
|
903
|
+
EndIf
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
### 44. Invalid field name
|
|
907
|
+
|
|
908
|
+
**Error Message:** `Field 'A1_XTEST' not found in alias 'SA1'`
|
|
909
|
+
|
|
910
|
+
**Cause:** Referencing a field that does not exist in the SX3 dictionary for this table, or a custom field that was not created.
|
|
911
|
+
|
|
912
|
+
**Solution:**
|
|
913
|
+
```advpl
|
|
914
|
+
// Check field exists in SX3 before accessing:
|
|
915
|
+
If FieldPos("A1_XTEST") > 0
|
|
916
|
+
cVal := SA1->A1_XTEST
|
|
917
|
+
Else
|
|
918
|
+
Conout("Field A1_XTEST not found in SA1 dictionary")
|
|
919
|
+
cVal := ""
|
|
920
|
+
EndIf
|
|
921
|
+
|
|
922
|
+
// Verify field in SX3:
|
|
923
|
+
// DbSelectArea("SX3")
|
|
924
|
+
// DbSetOrder(1) // X3_ARQUIVO + X3_CAMPO
|
|
925
|
+
// DbSeek("SA1" + "A1_XTEST")
|
|
926
|
+
```
|
|
927
|
+
|
|
928
|
+
### 45. Corrupted index
|
|
929
|
+
|
|
930
|
+
**Error Message:** `Index file corrupted` or inconsistent DbSeek results
|
|
931
|
+
|
|
932
|
+
**Cause:** AppServer crash during index update, disk failure, or concurrent uncontrolled writes.
|
|
933
|
+
|
|
934
|
+
**Solution:**
|
|
935
|
+
```advpl
|
|
936
|
+
// Rebuild index for the affected table:
|
|
937
|
+
// Option 1: Via APSDU - select table, rebuild indexes
|
|
938
|
+
// Option 2: Via code (requires exclusive access)
|
|
939
|
+
DbSelectArea("SA1")
|
|
940
|
+
If FLock()
|
|
941
|
+
DbClearIndex()
|
|
942
|
+
DbSetIndex(RetSqlName("SA1") + OrdBagExt())
|
|
943
|
+
DbUnlock()
|
|
944
|
+
Conout("Index rebuilt for SA1")
|
|
945
|
+
EndIf
|
|
946
|
+
|
|
947
|
+
// Prevention: ensure proper MsUnlock() after RecLock()
|
|
948
|
+
// and clean AppServer shutdown procedures
|
|
949
|
+
```
|
|
950
|
+
|
|
951
|
+
---
|
|
952
|
+
|
|
953
|
+
## Network/REST Errors
|
|
954
|
+
|
|
955
|
+
### 46. HTTP timeout
|
|
956
|
+
|
|
957
|
+
**Error Message:** `HTTP request timeout` or `Connection timed out`
|
|
958
|
+
|
|
959
|
+
**Cause:** The remote server is slow to respond or unreachable. Default timeouts may be too short for large payloads.
|
|
960
|
+
|
|
961
|
+
**Solution:**
|
|
962
|
+
```advpl
|
|
963
|
+
// Set appropriate timeout
|
|
964
|
+
Local oRest := FWRest():New("https://api.example.com")
|
|
965
|
+
oRest:SetTimeout(30) // 30 seconds
|
|
966
|
+
|
|
967
|
+
If oRest:Get("/endpoint")
|
|
968
|
+
cResponse := oRest:GetResult()
|
|
969
|
+
Else
|
|
970
|
+
Conout("HTTP Error: " + cValToChar(oRest:GetLastError()))
|
|
971
|
+
Conout("Check network connectivity and server availability")
|
|
972
|
+
EndIf
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
### 47. Connection refused
|
|
976
|
+
|
|
977
|
+
**Error Message:** `Connection refused` or `ECONNREFUSED`
|
|
978
|
+
|
|
979
|
+
**Cause:** The target server is not listening on the specified port, firewall blocking, or wrong URL/port.
|
|
980
|
+
|
|
981
|
+
**Solution:**
|
|
982
|
+
```advpl
|
|
983
|
+
// Verify URL and port are correct
|
|
984
|
+
// Check firewall rules on both AppServer and target server
|
|
985
|
+
// Test connectivity: ping and telnet from the AppServer machine
|
|
986
|
+
|
|
987
|
+
Local oRest := FWRest():New("https://api.example.com")
|
|
988
|
+
If !oRest:Get("/health")
|
|
989
|
+
Conout("Connection failed to api.example.com")
|
|
990
|
+
Conout("Error: " + cValToChar(oRest:GetLastError()))
|
|
991
|
+
Conout("Check: URL, port, firewall, DNS resolution")
|
|
992
|
+
EndIf
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
### 48. Invalid JSON response
|
|
996
|
+
|
|
997
|
+
**Error Message:** `JSON parse error` or unexpected response format
|
|
998
|
+
|
|
999
|
+
**Cause:** The server returned non-JSON content (HTML error page, empty response) or malformed JSON.
|
|
1000
|
+
|
|
1001
|
+
**Solution:**
|
|
1002
|
+
```advpl
|
|
1003
|
+
// Always validate response before parsing
|
|
1004
|
+
Local oRest := FWRest():New("https://api.example.com")
|
|
1005
|
+
If oRest:Get("/data")
|
|
1006
|
+
Local cResponse := oRest:GetResult()
|
|
1007
|
+
|
|
1008
|
+
// Check if response looks like JSON
|
|
1009
|
+
If Left(Alltrim(cResponse), 1) $ "{["
|
|
1010
|
+
Local oJson := JsonObject():New()
|
|
1011
|
+
If oJson:FromJson(cResponse) == 0
|
|
1012
|
+
// Valid JSON - process
|
|
1013
|
+
cValue := oJson:GetJsonText("field")
|
|
1014
|
+
Else
|
|
1015
|
+
Conout("Invalid JSON: " + cResponse)
|
|
1016
|
+
EndIf
|
|
1017
|
+
FreeObj(oJson)
|
|
1018
|
+
Else
|
|
1019
|
+
Conout("Response is not JSON: " + Left(cResponse, 200))
|
|
1020
|
+
EndIf
|
|
1021
|
+
EndIf
|
|
1022
|
+
```
|
|
1023
|
+
|
|
1024
|
+
### 49. Authentication failed (401)
|
|
1025
|
+
|
|
1026
|
+
**Error Message:** `HTTP 401 Unauthorized` or `Authentication required`
|
|
1027
|
+
|
|
1028
|
+
**Cause:** Missing, expired, or invalid authentication token/credentials.
|
|
1029
|
+
|
|
1030
|
+
**Solution:**
|
|
1031
|
+
```advpl
|
|
1032
|
+
// Basic Auth
|
|
1033
|
+
Local oRest := FWRest():New("https://api.example.com")
|
|
1034
|
+
oRest:SetAuthorization("Basic " + Encode64(cUser + ":" + cPassword))
|
|
1035
|
+
|
|
1036
|
+
// Bearer Token
|
|
1037
|
+
oRest:SetAuthorization("Bearer " + cToken)
|
|
1038
|
+
|
|
1039
|
+
// Check token expiration before making requests:
|
|
1040
|
+
If dTokenExpiry < Date() .Or. cToken == ""
|
|
1041
|
+
cToken := RefreshAuthToken()
|
|
1042
|
+
If Empty(cToken)
|
|
1043
|
+
Conout("ERROR: Unable to obtain auth token")
|
|
1044
|
+
Return .F.
|
|
1045
|
+
EndIf
|
|
1046
|
+
EndIf
|
|
1047
|
+
```
|
|
1048
|
+
|
|
1049
|
+
### 50. SSL certificate error
|
|
1050
|
+
|
|
1051
|
+
**Error Message:** `SSL certificate problem` or `Unable to verify SSL certificate`
|
|
1052
|
+
|
|
1053
|
+
**Cause:** Self-signed certificate, expired certificate, or the CA certificate is not trusted by the AppServer.
|
|
1054
|
+
|
|
1055
|
+
**Solution:**
|
|
1056
|
+
```advpl
|
|
1057
|
+
// Option 1: Add CA certificate to AppServer trust store
|
|
1058
|
+
// Copy .pem certificate to AppServer cert directory
|
|
1059
|
+
// Configure in appserver.ini:
|
|
1060
|
+
// [SSLConfigure]
|
|
1061
|
+
// CertificateClient=cert\client.pem
|
|
1062
|
+
// KeyClient=cert\client.key
|
|
1063
|
+
|
|
1064
|
+
// Option 2: Disable SSL verification (DEVELOPMENT ONLY - never in production)
|
|
1065
|
+
Local oRest := FWRest():New("https://api.example.com")
|
|
1066
|
+
oRest:SetSslVerify(.F.) // DANGER: disables all SSL verification
|
|
1067
|
+
```
|
|
1068
|
+
|
|
1069
|
+
---
|
|
1070
|
+
|
|
1071
|
+
## Quick Lookup Index
|
|
1072
|
+
|
|
1073
|
+
| # | Error | Category |
|
|
1074
|
+
|---|-------|----------|
|
|
1075
|
+
| 1 | Syntax error / Unexpected token | Compilation |
|
|
1076
|
+
| 2 | Variable already declared | Compilation |
|
|
1077
|
+
| 3 | Function not found | Compilation |
|
|
1078
|
+
| 4 | Missing END/ENDDO/ENDIF | Compilation |
|
|
1079
|
+
| 5 | Missing operator | Compilation |
|
|
1080
|
+
| 6 | Type clash in expression | Compilation |
|
|
1081
|
+
| 7 | #Include file not found | Compilation |
|
|
1082
|
+
| 8 | Duplicate function name | Compilation |
|
|
1083
|
+
| 9 | Too many parameters | Compilation |
|
|
1084
|
+
| 10 | Missing RETURN | Compilation |
|
|
1085
|
+
| 11 | Invalid character in source | Compilation |
|
|
1086
|
+
| 12 | Ambiguous reference | Compilation |
|
|
1087
|
+
| 13 | Missing TOTVS.CH | Compilation |
|
|
1088
|
+
| 14 | Invalid preprocessor directive | Compilation |
|
|
1089
|
+
| 15 | Class/Method not found (TLPP) | Compilation |
|
|
1090
|
+
| 16 | Variable does not exist | Runtime |
|
|
1091
|
+
| 17 | Array out of bounds | Runtime |
|
|
1092
|
+
| 18 | Type mismatch | Runtime |
|
|
1093
|
+
| 19 | Divide by zero | Runtime |
|
|
1094
|
+
| 20 | NIL value in expression | Runtime |
|
|
1095
|
+
| 21 | Invalid alias | Runtime |
|
|
1096
|
+
| 22 | WorkArea not in use | Runtime |
|
|
1097
|
+
| 23 | RecLock timeout | Runtime |
|
|
1098
|
+
| 24 | Code block evaluation error | Runtime |
|
|
1099
|
+
| 25 | Object method not found | Runtime |
|
|
1100
|
+
| 26 | Stack overflow | Runtime |
|
|
1101
|
+
| 27 | Memory allocation error | Runtime |
|
|
1102
|
+
| 28 | String too long | Runtime |
|
|
1103
|
+
| 29 | Date conversion error | Runtime |
|
|
1104
|
+
| 30 | Numeric overflow | Runtime |
|
|
1105
|
+
| 31 | Invalid function argument | Runtime |
|
|
1106
|
+
| 32 | Thread error | Runtime |
|
|
1107
|
+
| 33 | DLL load failure | Runtime |
|
|
1108
|
+
| 34 | Connection refused (DB) | Runtime |
|
|
1109
|
+
| 35 | Encoding/charset error | Runtime |
|
|
1110
|
+
| 36 | Table/alias not found | Database |
|
|
1111
|
+
| 37 | Index not found | Database |
|
|
1112
|
+
| 38 | Record lock timeout | Database |
|
|
1113
|
+
| 39 | Transaction error | Database |
|
|
1114
|
+
| 40 | SQL syntax error | Database |
|
|
1115
|
+
| 41 | Connection lost | Database |
|
|
1116
|
+
| 42 | Deadlock detected | Database |
|
|
1117
|
+
| 43 | Exclusive lock required | Database |
|
|
1118
|
+
| 44 | Invalid field name | Database |
|
|
1119
|
+
| 45 | Corrupted index | Database |
|
|
1120
|
+
| 46 | HTTP timeout | Network/REST |
|
|
1121
|
+
| 47 | Connection refused | Network/REST |
|
|
1122
|
+
| 48 | Invalid JSON response | Network/REST |
|
|
1123
|
+
| 49 | Authentication failed (401) | Network/REST |
|
|
1124
|
+
| 50 | SSL certificate error | Network/REST |
|