or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

binding-specs.mddecorators.mderror-handling.mdfield-initialization.mdindex.mdobject-graph.mdscoping.md

error-handling.mddocs/

0

# Error Handling

1

2

Comprehensive error system providing clear, actionable feedback for dependency injection issues, from binding conflicts to circular dependencies. All errors inherit from the base `Error` class.

3

4

## Capabilities

5

6

### Base Error Class

7

8

Base exception class for all Pinject-related errors.

9

10

```python { .api }

11

class Error(Exception):

12

"""Base exception class for all Pinject errors."""

13

```

14

15

### Binding Resolution Errors

16

17

Errors related to resolving dependencies and finding appropriate bindings.

18

19

```python { .api }

20

class AmbiguousArgNameError(Error):

21

"""Multiple bindings match the same argument name, creating ambiguity."""

22

23

class MissingRequiredBindingError(Error):

24

"""Required binding not found during dependency resolution."""

25

26

class NothingInjectableForArgError(Error):

27

"""No injectable found for a required argument."""

28

29

class OnlyInstantiableViaProviderFunctionError(Error):

30

"""Class can only be instantiated through a provider function."""

31

32

class NonExplicitlyBoundClassError(Error):

33

"""Class not explicitly bound when only_use_explicit_bindings=True."""

34

```

35

36

### Binding Configuration Errors

37

38

Errors that occur during binding specification and configuration.

39

40

```python { .api }

41

class ConflictingExplicitBindingsError(Error):

42

"""Multiple explicit bindings defined for the same key."""

43

44

class ConflictingRequiredBindingError(Error):

45

"""Conflicting implicit bindings for the same requirement."""

46

47

class InvalidBindingTargetError(Error):

48

"""Binding target has wrong type for the binding."""

49

50

class MultipleBindingTargetArgsError(Error):

51

"""Multiple binding targets specified for the same key."""

52

53

class NoBindingTargetArgsError(Error):

54

"""No binding target specified when required."""

55

56

class EmptyBindingSpecError(Error):

57

"""BindingSpec has neither configure() method nor provider methods."""

58

```

59

60

### Decorator Usage Errors

61

62

Errors related to incorrect usage of Pinject decorators.

63

64

```python { .api }

65

class DecoratorAppliedToNonInitError(Error):

66

"""Decorator applied to non-__init__ method."""

67

68

class DuplicateDecoratorError(Error):

69

"""Same decorator applied twice to the same method."""

70

71

class EmptyProvidesDecoratorError(Error):

72

"""@provides() decorator used without arguments."""

73

74

class TooManyArgsToInjectDecoratorError(Error):

75

"""Both arg_names and all_except specified in @inject decorator."""

76

77

class NoRemainingArgsToInjectError(Error):

78

"""All arguments marked as directly passed, leaving none to inject."""

79

80

class PargsDisallowedWhenCopyingArgsError(Error):

81

"""*args not allowed with copy_args decorators."""

82

```

83

84

### Argument and Annotation Errors

85

86

Errors related to argument specification and annotation handling.

87

88

```python { .api }

89

class NoSuchArgError(Error):

90

"""Reference to non-existent argument."""

91

92

class NoSuchArgToInjectError(Error):

93

"""Cannot inject into non-existent argument."""

94

95

class MultipleAnnotationsForSameArgError(Error):

96

"""Same argument annotated multiple times."""

97

98

class DirectlyPassingInjectedArgsError(Error):

99

"""Injected arguments passed directly to provider function."""

100

101

class WrongArgTypeError(Error):

102

"""Argument has wrong type."""

103

104

class WrongArgElementTypeError(Error):

105

"""Array/sequence element has wrong type."""

106

107

class EmptySequenceArgError(Error):

108

"""Empty sequence provided where non-empty sequence expected."""

109

```

110

111

### Scoping Errors

112

113

Errors related to object scope configuration and usage.

114

115

```python { .api }

116

class BadDependencyScopeError(Error):

117

"""Invalid dependency relationship between scopes."""

118

119

class UnknownScopeError(Error):

120

"""Reference to unknown scope identifier."""

121

122

class OverridingDefaultScopeError(Error):

123

"""Attempt to override built-in scope (SINGLETON, PROTOTYPE)."""

124

```

125

126

### Circular Dependency Errors

127

128

Errors related to circular dependency detection.

129

130

```python { .api }

131

class CyclicInjectionError(Error):

132

"""Circular dependency detected in object graph."""

133

```

134

135

### Method Configuration Errors

136

137

Errors related to BindingSpec method configuration.

138

139

```python { .api }

140

class ConfigureMethodMissingArgsError(Error):

141

"""BindingSpec configure method missing required arguments."""

142

```

143

144

### Injection Policy Errors

145

146

Errors related to injection policies and restrictions.

147

148

```python { .api }

149

class InjectingNoneDisallowedError(Error):

150

"""None injection attempted when allow_injecting_none=False."""

151

```

152

153

## Usage Examples

154

155

### Handling Ambiguous Bindings

156

157

```python

158

import pinject

159

160

class DatabaseService(object):

161

def __init__(self):

162

pass

163

164

class MockDatabaseService(object):

165

def __init__(self):

166

pass

167

168

# This will cause AmbiguousArgNameError

169

class UserService(object):

170

def __init__(self, database_service): # Ambiguous: which DatabaseService?

171

self.db = database_service

172

173

try:

174

obj_graph = pinject.new_object_graph(classes=[DatabaseService, MockDatabaseService])

175

user_service = obj_graph.provide(UserService)

176

except pinject.AmbiguousArgNameError as e:

177

print(f"Ambiguous binding: {e}")

178

179

# Solution: Use explicit bindings or annotations

180

class MyBindingSpec(pinject.BindingSpec):

181

def configure(self, bind):

182

bind('database_service').to_class(DatabaseService)

183

184

obj_graph = pinject.new_object_graph(

185

classes=[DatabaseService, MockDatabaseService],

186

binding_specs=[MyBindingSpec()]

187

)

188

user_service = obj_graph.provide(UserService) # Success

189

```

190

191

### Handling Missing Bindings

192

193

```python

194

import pinject

195

196

class UserService(object):

197

def __init__(self, database_service): # database_service not available

198

self.db = database_service

199

200

try:

201

obj_graph = pinject.new_object_graph()

202

user_service = obj_graph.provide(UserService)

203

except pinject.MissingRequiredBindingError as e:

204

print(f"Missing binding: {e}")

205

print("Solution: Provide the required class or binding")

206

207

# Solution: Add the missing class

208

class DatabaseService(object):

209

def __init__(self):

210

pass

211

212

obj_graph = pinject.new_object_graph(classes=[DatabaseService])

213

user_service = obj_graph.provide(UserService) # Success

214

```

215

216

### Handling Circular Dependencies

217

218

```python

219

import pinject

220

221

class ServiceA(object):

222

def __init__(self, service_b):

223

self.service_b = service_b

224

225

class ServiceB(object):

226

def __init__(self, service_a):

227

self.service_a = service_a

228

229

try:

230

obj_graph = pinject.new_object_graph()

231

service_a = obj_graph.provide(ServiceA)

232

except pinject.CyclicInjectionError as e:

233

print(f"Circular dependency: {e}")

234

235

# Solution: Break the cycle with lazy injection or redesign

236

class ServiceA(object):

237

def __init__(self, service_b):

238

self.service_b = service_b

239

240

class ServiceB(object):

241

def __init__(self):

242

self.service_a = None # Set later to break cycle

243

244

def set_service_a(self, service_a):

245

self.service_a = service_a

246

247

obj_graph = pinject.new_object_graph()

248

service_a = obj_graph.provide(ServiceA)

249

service_b = obj_graph.provide(ServiceB)

250

service_b.set_service_a(service_a) # Manual resolution

251

```

252

253

### Handling Decorator Errors

254

255

```python

256

import pinject

257

258

class InvalidService(object):

259

@pinject.inject(['nonexistent_arg'])

260

def __init__(self, real_arg):

261

self.arg = real_arg

262

263

try:

264

obj_graph = pinject.new_object_graph()

265

service = obj_graph.provide(InvalidService)

266

except pinject.NoSuchArgToInjectError as e:

267

print(f"Invalid injection specification: {e}")

268

269

# Solution: Fix the decorator

270

class ValidService(object):

271

@pinject.inject(['real_arg'])

272

def __init__(self, real_arg):

273

self.arg = real_arg

274

```

275

276

### Handling Scope Errors

277

278

```python

279

import pinject

280

281

class MyBindingSpec(pinject.BindingSpec):

282

def configure(self, bind):

283

# This will cause UnknownScopeError

284

bind('service').to_class(object, in_scope='unknown_scope')

285

286

try:

287

obj_graph = pinject.new_object_graph(binding_specs=[MyBindingSpec()])

288

except pinject.UnknownScopeError as e:

289

print(f"Unknown scope: {e}")

290

291

# Solution: Use valid scope or define custom scope

292

class ValidBindingSpec(pinject.BindingSpec):

293

def configure(self, bind):

294

bind('service').to_class(object, in_scope=pinject.SINGLETON)

295

```

296

297

### Error Context and Debugging

298

299

```python

300

import pinject

301

302

# Enable detailed error reporting

303

obj_graph = pinject.new_object_graph(use_short_stack_traces=False)

304

305

class ComplexService(object):

306

def __init__(self, dep1, dep2, dep3):

307

pass

308

309

try:

310

service = obj_graph.provide(ComplexService)

311

except pinject.Error as e:

312

# All Pinject errors provide detailed context

313

print(f"Error type: {type(e).__name__}")

314

print(f"Error message: {e}")

315

print(f"Error occurred during: ComplexService instantiation")

316

317

# Errors include location information and context

318

# to help identify the exact source of the problem

319

```