diff --git a/core/vm/errors.go b/core/vm/errors.go
index 116fbe4565562fba6cfc219b96ccd59835c4e9de..1766bf9fbb6778c4dbb214c21333bd91540bde54 100644
--- a/core/vm/errors.go
+++ b/core/vm/errors.go
@@ -26,3 +26,4 @@ import (
 var OutOfGasError = errors.New("Out of gas")
 var CodeStoreOutOfGasError = errors.New("Contract creation code storage out of gas")
 var DepthError = fmt.Errorf("Max call depth exceeded (%d)", params.CallCreateDepth)
+var TraceLimitReachedError = errors.New("The number of logs reached the specified limit")
diff --git a/core/vm/logger.go b/core/vm/logger.go
index ae62b6b57324faec14a2df80b2cf6c4ce7cc03db..9e13d703be78cc7c53b6bb8774aee7c36e0f3fef 100644
--- a/core/vm/logger.go
+++ b/core/vm/logger.go
@@ -42,6 +42,7 @@ type LogConfig struct {
 	DisableStack   bool // disable stack capture
 	DisableStorage bool // disable storage capture
 	FullStorage    bool // show full storage (slow)
+	Limit          int  // maximum length of output, but zero means unlimited
 }
 
 // StructLog is emitted to the Environment each cycle and lists information about the current internal state
@@ -64,7 +65,7 @@ type StructLog struct {
 // Note that reference types are actual VM data structures; make copies
 // if you need to retain them beyond the current call.
 type Tracer interface {
-	CaptureState(env Environment, pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *Stack, contract *Contract, depth int, err error)
+	CaptureState(env Environment, pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error
 }
 
 // StructLogger is an EVM state logger and implements Tracer.
@@ -93,7 +94,12 @@ func NewStructLogger(cfg *LogConfig) *StructLogger {
 // captureState logs a new structured log message and pushes it out to the environment
 //
 // captureState also tracks SSTORE ops to track dirty values.
-func (l *StructLogger) CaptureState(env Environment, pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *Stack, contract *Contract, depth int, err error) {
+func (l *StructLogger) CaptureState(env Environment, pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
+	// check if already accumulated the specified number of logs
+	if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) {
+		return TraceLimitReachedError
+	}
+
 	// initialise new changed values storage container for this contract
 	// if not present.
 	if l.changedValues[contract.Address()] == nil {
@@ -152,6 +158,7 @@ func (l *StructLogger) CaptureState(env Environment, pc uint64, op OpCode, gas,
 	log := StructLog{pc, op, new(big.Int).Set(gas), cost, mem, stck, storage, env.Depth(), err}
 
 	l.logs = append(l.logs, log)
+	return nil
 }
 
 // StructLogs returns a list of captured log entries
diff --git a/core/vm/vm.go b/core/vm/vm.go
index 205934822a8e760316889c85947f35fd04354acc..09cddc2f8b1737d55ad2c778fa11d214be9dc5d4 100644
--- a/core/vm/vm.go
+++ b/core/vm/vm.go
@@ -188,7 +188,10 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
 		mem.Resize(newMemSize.Uint64())
 		// Add a log message
 		if evm.cfg.Debug {
-			evm.cfg.Tracer.CaptureState(evm.env, pc, op, contract.Gas, cost, mem, stack, contract, evm.env.Depth(), nil)
+			err = evm.cfg.Tracer.CaptureState(evm.env, pc, op, contract.Gas, cost, mem, stack, contract, evm.env.Depth(), nil)
+			if err != nil {
+				return nil, err
+			}
 		}
 
 		if opPtr := evm.jumpTable[op]; opPtr.valid {
diff --git a/internal/ethapi/tracer.go b/internal/ethapi/tracer.go
index 16ec6ebf0a187b4d09f7c4657c28d33947189279..c6d4f814ec39a4275b571c8f31e15a8c71c7b921 100644
--- a/internal/ethapi/tracer.go
+++ b/internal/ethapi/tracer.go
@@ -278,7 +278,7 @@ func wrapError(context string, err error) error {
 }
 
 // CaptureState implements the Tracer interface to trace a single step of VM execution
-func (jst *JavascriptTracer) CaptureState(env vm.Environment, pc uint64, op vm.OpCode, gas, cost *big.Int, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) {
+func (jst *JavascriptTracer) CaptureState(env vm.Environment, pc uint64, op vm.OpCode, gas, cost *big.Int, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error {
 	if jst.err == nil {
 		jst.memory.memory = memory
 		jst.stack.stack = stack
@@ -301,6 +301,7 @@ func (jst *JavascriptTracer) CaptureState(env vm.Environment, pc uint64, op vm.O
 			jst.err = wrapError("step", err)
 		}
 	}
+	return nil
 }
 
 // GetResult calls the Javascript 'result' function and returns its value, or any accumulated error